diff --git a/fern.schema.json b/fern.schema.json index 1087d676904..5bf909d0050 100644 --- a/fern.schema.json +++ b/fern.schema.json @@ -2656,26 +2656,6 @@ "type": "null" } ] - }, - "transport": { - "oneOf": [ - { - "$ref": "#/definitions/service.ServiceTransport" - }, - { - "type": "null" - } - ] - }, - "source": { - "oneOf": [ - { - "$ref": "#/definitions/source.SourceSchema" - }, - { - "type": "null" - } - ] } }, "required": [ diff --git a/fern/apis/fern-definition/definition/service.yml b/fern/apis/fern-definition/definition/service.yml index 3e3106905f8..e3f2e1bd596 100644 --- a/fern/apis/fern-definition/definition/service.yml +++ b/fern/apis/fern-definition/definition/service.yml @@ -1,4 +1,4 @@ -imports: +imports: commons: commons.yml types: types.yml examples: examples.yml @@ -6,37 +6,37 @@ imports: source: source.yml variables: variables.yml -types: - HttpServiceSchema: - extends: +types: + HttpServiceSchema: + extends: - commons.DeclarationWithoutDocsSchema - commons.WithDisplayName - properties: + properties: auth: boolean url: optional base-path: string path-parameters: optional> idempotent: optional headers: optional> - transport: optional + transport: optional source: optional endpoints: map - ServiceTransport: - properties: - grpc: optional - - GrpcTransport: - properties: - service-name: + ServiceTransport: + properties: + grpc: optional + + GrpcTransport: + properties: + service-name: type: string docs: "The name of the gRPC service." - - HttpEndpointSchema: - extends: + + HttpEndpointSchema: + extends: - commons.WithDisplayName - commons.DeclarationSchema - properties: + properties: method: optional base-path: optional path: string @@ -51,144 +51,142 @@ types: errors: optional examples: optional> pagination: optional - transport: optional - source: optional - - HttpMethodSchema: - enum: + + HttpMethodSchema: + enum: - GET - POST - PUT - PATCH - DELETE - - HttpRequest: + + HttpRequest: discriminated: false - union: + union: - string - HttpRequestSchema HttpRequestSchema: - extends: + extends: - commons.WithName - commons.WithDocsSchema - properties: + properties: content-type: optional query-parameters: optional> headers: optional> body: optional - + TypeReferenceDeclarationWithEnvOverride: discriminated: false - union: + union: - string - TypeReferenceDeclarationWithEnvOverrideSchema - TypeReferenceDeclarationWithEnvOverrideSchema: + TypeReferenceDeclarationWithEnvOverrideSchema: extends: types.TypeReferenceDeclarationWithName - properties: + properties: env: optional HttpHeaderSchema: TypeReferenceDeclarationWithEnvOverride - - HttpRequestBodySchema: + + HttpRequestBodySchema: discriminated: false - union: + union: - string - HttpReferencedRequestBodySchema - HttpInlineRequestBodySchema - - HttpReferencedRequestBodySchema: - extends: + + HttpReferencedRequestBodySchema: + extends: - commons.WithDocsSchema properties: type: string - HttpInlineRequestBodySchema: - properties: + HttpInlineRequestBodySchema: + properties: extends: optional extra-properties: optional properties: optional> - - HttpInlineRequestBodyPropertySchema: + + HttpInlineRequestBodyPropertySchema: discriminated: false - union: + union: - string - TypeReferenceDeclarationWithContentTypeSchema - - TypeReferenceDeclarationWithContentTypeSchema: + + TypeReferenceDeclarationWithContentTypeSchema: extends: types.TypeReferenceDeclarationWithName - properties: + properties: content-type: optional - - HttpQueryParameterSchema: + + HttpQueryParameterSchema: discriminated: false - union: + union: - string - QueryParameterTypeReferenceDetailed - - QueryParameterTypeReferenceDetailed: - extends: + + QueryParameterTypeReferenceDetailed: + extends: - types.TypeReferenceDeclarationWithName - properties: + properties: allow-multiple: optional - - HttpResponseSchema: + + HttpResponseSchema: discriminated: false - union: + union: - string - HttpResponseSchemaDetailed - - HttpResponseSchemaDetailed: - extends: + + HttpResponseSchemaDetailed: + extends: - commons.WithDocsSchema - properties: + properties: type: string property: optional status-code: optional - HttpResponseStreamSchema: + HttpResponseStreamSchema: discriminated: false - union: + union: - string - HttpResponseStreamSchemaDetailed - - HttpResponseStreamSchemaDetailed: - extends: + + HttpResponseStreamSchemaDetailed: + extends: - commons.WithDocsSchema - properties: + properties: type: string format: optional terminator: optional - StreamFormat: - enum: + StreamFormat: + enum: - sse - json - - HttpPathParameterSchema: + + HttpPathParameterSchema: discriminated: false - union: + union: - types.TypeReferenceSchema - variables.VariableReferenceSchema - - Pagination: + + Pagination: discriminated: false - union: + union: - pagination.PaginationSchema - boolean - - ResponseErrorsSchema: + + ResponseErrorsSchema: type: list - ResponseError: + ResponseError: discriminated: false - union: + union: - string - ResponseErrorWithDocsSchema - - ResponseErrorWithDocsSchema: - extends: + + ResponseErrorWithDocsSchema: + extends: - commons.WithDocsSchema - properties: - error: string + properties: + error: string \ No newline at end of file diff --git a/fern/docs.yml b/fern/docs.yml index af0a4dff7c0..761ce377884 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -448,13 +448,6 @@ navigation: - page: SDK Snippets icon: fa-regular fa-message-code path: ./pages/fern-docs/config/sdk-snippets.mdx - - section: API Playground - path: ./pages/fern-docs/content/api-playground.mdx - icon: fa-regular fa-square-terminal - contents: - - page: Advanced Configuration - icon: fa-regular fa-wrench - path: ./pages/fern-docs/content/customize-api-playground.mdx - page: Endpoint Errors icon: fa-regular fa-exclamation-triangle path: ./pages/fern-docs/config/endpoint-errors.mdx @@ -464,6 +457,9 @@ navigation: - page: Write Markdown in API Reference icon: fa-regular fa-pencil path: ./pages/fern-docs/content/api-ref-content.mdx + - page: Customize API Playground + icon: fa-regular fa-square-terminal + path: ./pages/fern-docs/content/customize-api-playground.mdx - section: Integrations slug: integrations diff --git a/fern/pages/changelogs/csharp-sdk/2024-10-30.mdx b/fern/pages/changelogs/csharp-sdk/2024-10-30.mdx index 1e22e53fc29..7dd32f21be9 100644 --- a/fern/pages/changelogs/csharp-sdk/2024-10-30.mdx +++ b/fern/pages/changelogs/csharp-sdk/2024-10-30.mdx @@ -1,86 +1,3 @@ ## 1.8.5 -**`(feat):`** Add forward-compatible enums. -Set `experimental-enable-forward-compatible-enums` to `true` in the configuration to generate forward-compatible enums. - -With forward-compatible enums you can create and parse an enum value that is not predefined. - -- Forward compatible enums are not compatible with the previously generated native enums. - This is a breaking change for the users of the generated SDK, but only users using switch-case statements are affected. -- Use the `Value` property to get the string value of the enum. -- For each value in the enum, - - a public static property is generated, which is an instance of the enum class, - - a public static property is generated within the nested `Values` class with the string value of the enum. - -Here's a before and after for creating and parsing a resource with a predefined enum value and a custom enum value: - -**Before**: - -```csharp -var resource = client.CreateResource(new Resource { Id = "2", EnumProperty = MyEnum.Value2 } ); -// The line below does not compile because the enum does not have a `Value3` value. -// resource = client.CreateResource(new Resource { Id = "3", EnumProperty = MyEnum.Value3 } ); -resource = client.GetResource("3"); -switch(resource.EnumProperty) -{ - case MyEnum.Value1: - Console.WriteLine("Value1"); - break; - case MyEnum.Value2: - Console.WriteLine("Value2"); - break; - default: - // this will never be reached until the SDK is updated with the new enum value - Console.WriteLine("Unknown"); - break; -} -if(resource.EnumProperty == MyEnum.Value1) -{ - Console.WriteLine("Value1"); -} -else if (resource.EnumProperty == MyEnum.Value2) -{ - Console.WriteLine("Value2"); -} -else -{ - // this will never be reached until the SDK is updated with the new enum value - Console.WriteLine("Unknown"); -} -``` - -No exception is thrown, but the output incorrectly shows `Value1` because .NET falls back to the first value in the enum. - -**After**: - -```csharp -var resource = client.CreateResource(new Resource { Id = "2", EnumProperty = MyEnum.Value2 } ); -resource = client.CreateResource(new Resource { Id = "3", EnumProperty = MyEnum.Custom("value3") } ); -resource = client.GetResource("3"); -switch(resource.EnumProperty.Value) -{ - case MyEnum.Values.Value1: - Console.WriteLine("Value1"); - break; - case MyEnum.Values.Value2: - Console.WriteLine("Value2"); - break; - default: - Console.WriteLine(resource.EnumProperty.Value); - break; -} -if(resource.EnumProperty == MyEnum.Value1) -{ - Console.WriteLine("Value1"); -} -else if (resource.EnumProperty == MyEnum.Value2) -{ - Console.WriteLine("Value2"); -} -else -{ - Console.WriteLine(resource.EnumProperty.Value); -} -``` - -The output correctly shows `Value3`. +**`(feat):`** Add forward compatible enums. Set `experimental-enable-forward-compatible-enums` to `true` in the configuration to generate forward compatible enums. diff --git a/fern/pages/fern-docs/content/customize-api-playground.mdx b/fern/pages/fern-docs/content/customize-api-playground.mdx index e16639cab90..866aa81f827 100644 --- a/fern/pages/fern-docs/content/customize-api-playground.mdx +++ b/fern/pages/fern-docs/content/customize-api-playground.mdx @@ -1,6 +1,6 @@ --- -title: Advanced configuration -description: Configure advanced settings like the server URLs reachable by the API playground and authentication with OAuth. +title: Customize your API Playground +description: Customize your API Playground Settings --- If you subscribe to Fern's Pro or Enterprise Plans, you can customize your API Playground settings to suit your customers needs. diff --git a/generators/python-v2/ast/.depcheckrc.json b/generators/python-v2/ast/.depcheckrc.json new file mode 100644 index 00000000000..a3a4f43188c --- /dev/null +++ b/generators/python-v2/ast/.depcheckrc.json @@ -0,0 +1,10 @@ +{ + "ignores": [ + "@types/jest", + "globals", + "@types/node" + ], + "ignore-patterns": [ + "lib" + ] +} \ No newline at end of file diff --git a/generators/python-v2/codegen/.prettierrc.cjs b/generators/python-v2/ast/.prettierrc.cjs similarity index 100% rename from generators/python-v2/codegen/.prettierrc.cjs rename to generators/python-v2/ast/.prettierrc.cjs diff --git a/generators/python-v2/codegen/package.json b/generators/python-v2/ast/package.json similarity index 94% rename from generators/python-v2/codegen/package.json rename to generators/python-v2/ast/package.json index 0d365ff1fd0..3b134f3b192 100644 --- a/generators/python-v2/codegen/package.json +++ b/generators/python-v2/ast/package.json @@ -1,5 +1,5 @@ { - "name": "@fern-api/pythonv2-codegen", + "name": "@fern-api/python-ast", "version": "0.0.0", "repository": { "type": "git", @@ -29,7 +29,6 @@ "dependencies": { "@fern-api/core-utils": "workspace:*", "@fern-api/generator-commons": "workspace:*", - "@fern-fern/ir-sdk": "53.7.0", "@wasm-fmt/ruff_fmt": "^0.6.1" }, "devDependencies": { diff --git a/generators/python-v2/codegen/src/ast/BaseInvocation.ts b/generators/python-v2/ast/src/BaseInvocation.ts similarity index 91% rename from generators/python-v2/codegen/src/ast/BaseInvocation.ts rename to generators/python-v2/ast/src/BaseInvocation.ts index 8de505cd55d..1dadcd8934b 100644 --- a/generators/python-v2/codegen/src/ast/BaseInvocation.ts +++ b/generators/python-v2/ast/src/BaseInvocation.ts @@ -1,8 +1,5 @@ -import { python } from ".."; -import { CodeBlock } from "./CodeBlock"; import { AstNode } from "./core/AstNode"; import { Writer } from "./core/Writer"; -import { Method } from "./Method"; import { MethodArgument } from "./MethodArgument"; import { Reference } from "./Reference"; diff --git a/generators/python-v2/codegen/src/ast/Class.ts b/generators/python-v2/ast/src/Class.ts similarity index 73% rename from generators/python-v2/codegen/src/ast/Class.ts rename to generators/python-v2/ast/src/Class.ts index 79a25d44324..5961baab2d3 100644 --- a/generators/python-v2/codegen/src/ast/Class.ts +++ b/generators/python-v2/ast/src/Class.ts @@ -1,14 +1,15 @@ import { Reference } from "./Reference"; import { AstNode } from "./core/AstNode"; import { Writer } from "./core/Writer"; -import { Field } from "./Field"; import { Decorator } from "./Decorator"; -import { CodeBlock } from "./CodeBlock"; +import { Field } from "./Field"; export declare namespace Class { interface Args { /* The name of the Python class */ name: string; + /* Documentation string for the class */ + docs?: string; /* The parent classes that this class inherits from */ extends_?: Reference[]; /* The decorators that should be applied to this class */ @@ -20,13 +21,16 @@ export class Class extends AstNode { public readonly name: string; public readonly extends_: Reference[]; public readonly decorators: Decorator[]; + public readonly fields: Field[] = []; + public readonly docs?: string; private statements: AstNode[] = []; - constructor({ name, extends_, decorators }: Class.Args) { + constructor({ docs, name, extends_, decorators }: Class.Args) { super(); this.name = name; this.extends_ = extends_ ?? []; this.decorators = decorators ?? []; + this.docs = docs; this.extends_.forEach((parentClassReference) => { this.addReference(parentClassReference); @@ -53,6 +57,20 @@ export class Class extends AstNode { writer.write(":"); writer.newLine(); + if (this.docs != null) { + writer.write('"""'); + writer.write(this.docs); + writer.write('"""'); + } + writer.writeNewLineIfLastLineNot(); + + writer.indent(); + this.fields.forEach((field) => { + field.write(writer); + writer.writeNewLineIfLastLineNot(); + }); + writer.dedent(); + writer.indent(); if (this.statements.length) { this.writeStatements({ writer }); @@ -62,14 +80,19 @@ export class Class extends AstNode { writer.dedent(); } - public addStatement(statement: AstNode): void { + public add(statement: AstNode): void { this.statements.push(statement); this.inheritReferences(statement); } + private writeStatements({ writer }: { writer: Writer }): void { this.statements.forEach((statement, index) => { statement.write(writer); writer.writeNewLineIfLastLineNot(); }); } + + public addField(field: Field): void { + this.add(field); + } } diff --git a/generators/python-v2/codegen/src/ast/ClassInstantiation.ts b/generators/python-v2/ast/src/ClassInstantiation.ts similarity index 68% rename from generators/python-v2/codegen/src/ast/ClassInstantiation.ts rename to generators/python-v2/ast/src/ClassInstantiation.ts index d83fccd0422..7ba4b08a12b 100644 --- a/generators/python-v2/codegen/src/ast/ClassInstantiation.ts +++ b/generators/python-v2/ast/src/ClassInstantiation.ts @@ -1,9 +1,3 @@ -import { python } from ".."; -import { CodeBlock } from "./CodeBlock"; -import { AstNode } from "./core/AstNode"; -import { Writer } from "./core/Writer"; -import { Method } from "./Method"; -import { MethodArgument } from "./MethodArgument"; import { Reference } from "./Reference"; import { BaseInvocation } from "./BaseInvocation"; diff --git a/generators/python-v2/codegen/src/ast/CodeBlock.ts b/generators/python-v2/ast/src/CodeBlock.ts similarity index 100% rename from generators/python-v2/codegen/src/ast/CodeBlock.ts rename to generators/python-v2/ast/src/CodeBlock.ts diff --git a/generators/python-v2/codegen/src/ast/Decorator.ts b/generators/python-v2/ast/src/Decorator.ts similarity index 72% rename from generators/python-v2/codegen/src/ast/Decorator.ts rename to generators/python-v2/ast/src/Decorator.ts index 8004d2794b1..77318acb177 100644 --- a/generators/python-v2/codegen/src/ast/Decorator.ts +++ b/generators/python-v2/ast/src/Decorator.ts @@ -1,9 +1,5 @@ import { AstNode } from "./core/AstNode"; import { Writer } from "./core/Writer"; -import { Reference } from "./Reference"; -import { BaseInvocation } from "./BaseInvocation"; -import { MethodInvocation } from "./MethodInvocation"; -import { ClassInstantiation } from "./ClassInstantiation"; export declare namespace Decorator { interface Args { diff --git a/generators/python-v2/codegen/src/ast/Field.ts b/generators/python-v2/ast/src/Field.ts similarity index 74% rename from generators/python-v2/codegen/src/ast/Field.ts rename to generators/python-v2/ast/src/Field.ts index 5707ac61dd9..37002d43d85 100644 --- a/generators/python-v2/codegen/src/ast/Field.ts +++ b/generators/python-v2/ast/src/Field.ts @@ -6,6 +6,8 @@ export declare namespace Field { export interface BaseArgs { /* The name of the field */ name: string; + /* The documentation for the field */ + docs?: string; } /* At least one of type or initializer must be defined @@ -24,12 +26,14 @@ export class Field extends AstNode { public readonly name: string; public readonly type: Type | undefined; public readonly initializer: AstNode | undefined; + public readonly docs: string | undefined; - constructor({ name, type, initializer }: Field.Args) { + constructor({ name, type, initializer, docs }: Field.Args) { super(); this.name = name; this.type = type; this.initializer = initializer; + this.docs = docs; this.inheritReferences(this.type); this.inheritReferences(this.initializer); @@ -46,5 +50,14 @@ export class Field extends AstNode { if (this.initializer !== undefined) { writer.write(` = ${this.initializer}`); } + + if (this.docs != null) { + writer.newLine(); + writer.write('"""'); + writer.newLine(); + writer.write(this.docs); + writer.newLine(); + writer.write('"""'); + } } } diff --git a/generators/python-v2/codegen/src/ast/Method.ts b/generators/python-v2/ast/src/Method.ts similarity index 86% rename from generators/python-v2/codegen/src/ast/Method.ts rename to generators/python-v2/ast/src/Method.ts index 82004db7f87..734a4ab36e0 100644 --- a/generators/python-v2/codegen/src/ast/Method.ts +++ b/generators/python-v2/ast/src/Method.ts @@ -2,10 +2,8 @@ import { AstNode } from "./core/AstNode"; import { Writer } from "./core/Writer"; import { Type } from "./Type"; import { CodeBlock } from "./CodeBlock"; -import { Reference } from "./Reference"; -import { Field } from "./Field"; import { Parameter } from "./Parameter"; -import { python } from ".."; +import { python } from "."; import { Decorator } from "./Decorator"; export enum ClassMethodType { @@ -19,13 +17,15 @@ export declare namespace Method { /* The name of the method */ name: string; /* The parameters of the method */ - parameters: Parameter[]; + parameters?: Parameter[]; /* The return type of the method */ return_?: Type; /* The docstring for the method */ docstring?: string; /* The type of the method if defined within the context of a class */ type?: ClassMethodType; + /* Whether the method is a static method */ + static_?: boolean; /* The decorators that should be applied to this method */ decorators?: Decorator[]; } @@ -39,15 +39,17 @@ export class Method extends AstNode { private readonly parameters: Parameter[]; private readonly decorators: Decorator[]; private readonly statements: AstNode[] = []; + private readonly static_: boolean; - constructor({ name, parameters, return_, docstring, type, decorators }: Method.Args) { + constructor({ static_, name, parameters, return_, docstring, type, decorators }: Method.Args) { super(); this.name = name; - this.parameters = parameters; + this.parameters = parameters ?? []; this.return = return_; this.docstring = docstring; this.type = type; this.decorators = decorators ?? []; + this.static_ = static_ ?? false; } public addStatement(statement: AstNode): void { @@ -56,6 +58,14 @@ export class Method extends AstNode { } public write(writer: Writer): void { + if (this.static_) { + this.decorators.push( + python.decorator({ + callable: python.codeBlock("staticmethod") + }) + ); + } + // Write decorators this.decorators.forEach((decorator) => { decorator.write(writer); diff --git a/generators/python-v2/codegen/src/ast/MethodArgument.ts b/generators/python-v2/ast/src/MethodArgument.ts similarity index 92% rename from generators/python-v2/codegen/src/ast/MethodArgument.ts rename to generators/python-v2/ast/src/MethodArgument.ts index d19d7006723..68491fc3c33 100644 --- a/generators/python-v2/codegen/src/ast/MethodArgument.ts +++ b/generators/python-v2/ast/src/MethodArgument.ts @@ -1,7 +1,5 @@ -import { CodeBlock } from "./CodeBlock"; import { AstNode } from "./core/AstNode"; import { Writer } from "./core/Writer"; -import { Type } from "./Type"; export declare namespace MethodArgument { interface Args { diff --git a/generators/python-v2/codegen/src/ast/MethodInvocation.ts b/generators/python-v2/ast/src/MethodInvocation.ts similarity index 68% rename from generators/python-v2/codegen/src/ast/MethodInvocation.ts rename to generators/python-v2/ast/src/MethodInvocation.ts index f1c2ea03d80..bc193e0fcd7 100644 --- a/generators/python-v2/codegen/src/ast/MethodInvocation.ts +++ b/generators/python-v2/ast/src/MethodInvocation.ts @@ -1,9 +1,3 @@ -import { python } from ".."; -import { CodeBlock } from "./CodeBlock"; -import { AstNode } from "./core/AstNode"; -import { Writer } from "./core/Writer"; -import { Method } from "./Method"; -import { MethodArgument } from "./MethodArgument"; import { Reference } from "./Reference"; import { BaseInvocation } from "./BaseInvocation"; diff --git a/generators/python-v2/codegen/src/ast/Operator.ts b/generators/python-v2/ast/src/Operator.ts similarity index 100% rename from generators/python-v2/codegen/src/ast/Operator.ts rename to generators/python-v2/ast/src/Operator.ts diff --git a/generators/python-v2/codegen/src/ast/OperatorType.ts b/generators/python-v2/ast/src/OperatorType.ts similarity index 100% rename from generators/python-v2/codegen/src/ast/OperatorType.ts rename to generators/python-v2/ast/src/OperatorType.ts diff --git a/generators/python-v2/codegen/src/ast/Parameter.ts b/generators/python-v2/ast/src/Parameter.ts similarity index 100% rename from generators/python-v2/codegen/src/ast/Parameter.ts rename to generators/python-v2/ast/src/Parameter.ts diff --git a/generators/python-v2/codegen/src/ast/PythonFile.ts b/generators/python-v2/ast/src/PythonFile.ts similarity index 97% rename from generators/python-v2/codegen/src/ast/PythonFile.ts rename to generators/python-v2/ast/src/PythonFile.ts index 9341258c918..16e31b47863 100644 --- a/generators/python-v2/codegen/src/ast/PythonFile.ts +++ b/generators/python-v2/ast/src/PythonFile.ts @@ -1,8 +1,5 @@ import { AstNode } from "./core/AstNode"; import { Writer } from "./core/Writer"; -import { Class } from "./Class"; -import { Method } from "./Method"; -import { CodeBlock } from "./CodeBlock"; import { Reference } from "./Reference"; import { ModulePath } from "./core/types"; diff --git a/generators/python-v2/codegen/src/ast/Reference.ts b/generators/python-v2/ast/src/Reference.ts similarity index 100% rename from generators/python-v2/codegen/src/ast/Reference.ts rename to generators/python-v2/ast/src/Reference.ts diff --git a/generators/python-v2/codegen/src/ast/Type.ts b/generators/python-v2/ast/src/Type.ts similarity index 85% rename from generators/python-v2/codegen/src/ast/Type.ts rename to generators/python-v2/ast/src/Type.ts index 650508e3cfb..d3ebda14da5 100644 --- a/generators/python-v2/codegen/src/ast/Type.ts +++ b/generators/python-v2/ast/src/Type.ts @@ -1,5 +1,5 @@ import { assertNever } from "@fern-api/core-utils"; -import { python } from ".."; +import { python } from "."; import { AstNode } from "./core/AstNode"; import { Writer } from "./core/Writer"; import { Reference } from "./Reference"; @@ -19,7 +19,9 @@ type InternalType = | Optional | Union | Any - | ReferenceType; + | ReferenceType + | Datetime + | Literal; interface Int { type: "int"; @@ -80,6 +82,10 @@ interface Union { values: Type[]; } +interface Datetime { + type: "datetime"; +} + interface Any { type: "any"; } @@ -89,6 +95,11 @@ interface ReferenceType { value: Reference; } +interface Literal { + type: "literal"; + value: string | number | boolean; +} + export class Type extends AstNode { private internalType: InternalType; @@ -176,12 +187,24 @@ export class Type extends AstNode { return anyType; } + public static datetime(): Type { + const datetimeType = new this({ type: "datetime" }); + datetimeType.addReference(python.reference({ name: "datetime", modulePath: ["datetime"] })); + return datetimeType; + } + public static reference(value: Reference): Type { const referenceType = new this({ type: "reference", value }); referenceType.addReference(value); return referenceType; } + public static literal(value: string | boolean | number): Type { + const literalType = new this({ type: "literal", value }); + literalType.addReference(python.reference({ name: "Literal", modulePath: ["typing"] })); + return literalType; + } + public write(writer: Writer): void { switch (this.internalType.type) { case "int": @@ -253,6 +276,16 @@ export class Type extends AstNode { case "reference": this.internalType.value.write(writer); break; + case "datetime": + writer.write("datetime"); + break; + case "literal": + if (typeof this.internalType.value === "string") { + writer.write(`Literal["${this.internalType.value}"]`); + } else { + writer.write(`Literal[${this.internalType.value}]`); + } + break; default: assertNever(this.internalType); } diff --git a/generators/python-v2/codegen/src/ast/TypeInstantiation.ts b/generators/python-v2/ast/src/TypeInstantiation.ts similarity index 100% rename from generators/python-v2/codegen/src/ast/TypeInstantiation.ts rename to generators/python-v2/ast/src/TypeInstantiation.ts diff --git a/generators/python-v2/codegen/src/ast/__test__/Class.test.ts b/generators/python-v2/ast/src/__test__/Class.test.ts similarity index 91% rename from generators/python-v2/codegen/src/ast/__test__/Class.test.ts rename to generators/python-v2/ast/src/__test__/Class.test.ts index 000e773d7ab..7386fb1ddfd 100644 --- a/generators/python-v2/codegen/src/ast/__test__/Class.test.ts +++ b/generators/python-v2/ast/src/__test__/Class.test.ts @@ -1,4 +1,4 @@ -import { python } from "../.."; +import { python } from ".."; import { Writer } from "../core/Writer"; describe("class", () => { @@ -20,10 +20,8 @@ describe("class", () => { const clazz = python.class_({ name: "Car" }); - clazz.addStatement( - python.field({ name: "color", type: python.Type.str(), initializer: python.codeBlock("'red'") }) - ); - clazz.addStatement( + clazz.add(python.field({ name: "color", type: python.Type.str(), initializer: python.codeBlock("'red'") })); + clazz.add( python.field({ name: "partNameById", type: python.Type.dict(python.Type.int(), python.Type.str()), @@ -98,9 +96,9 @@ describe("class", () => { parameters: [python.parameter({ name: "self", type: python.Type.str() })] }); innerMethod.addStatement(python.codeBlock('return "Inner method called"')); - innerClassDef.addStatement(innerMethod); + innerClassDef.add(innerMethod); - clazz.addStatement(innerClassDef); + clazz.add(innerClassDef); clazz.write(writer); expect(await writer.toStringFormatted()).toMatchSnapshot(); diff --git a/generators/python-v2/codegen/src/ast/__test__/ClassInstantiation.test.ts b/generators/python-v2/ast/src/__test__/ClassInstantiation.test.ts similarity index 97% rename from generators/python-v2/codegen/src/ast/__test__/ClassInstantiation.test.ts rename to generators/python-v2/ast/src/__test__/ClassInstantiation.test.ts index 04ee10cb0b4..193f06b4c9d 100644 --- a/generators/python-v2/codegen/src/ast/__test__/ClassInstantiation.test.ts +++ b/generators/python-v2/ast/src/__test__/ClassInstantiation.test.ts @@ -1,6 +1,5 @@ -import { MethodInvocation } from "../MethodInvocation"; import { Writer } from "../core/Writer"; -import { python } from "../.."; +import { python } from ".."; describe("ClassInstantiation", () => { let writer: Writer; diff --git a/generators/python-v2/codegen/src/ast/__test__/CodeBlock.test.ts b/generators/python-v2/ast/src/__test__/CodeBlock.test.ts similarity index 97% rename from generators/python-v2/codegen/src/ast/__test__/CodeBlock.test.ts rename to generators/python-v2/ast/src/__test__/CodeBlock.test.ts index eb14b3dccc9..f19a949905e 100644 --- a/generators/python-v2/codegen/src/ast/__test__/CodeBlock.test.ts +++ b/generators/python-v2/ast/src/__test__/CodeBlock.test.ts @@ -1,4 +1,4 @@ -import { python } from "../.."; +import { python } from ".."; import { Writer } from "../core/Writer"; describe("CodeBlock", () => { diff --git a/generators/python-v2/codegen/src/ast/__test__/Decorator.test.ts b/generators/python-v2/ast/src/__test__/Decorator.test.ts similarity index 98% rename from generators/python-v2/codegen/src/ast/__test__/Decorator.test.ts rename to generators/python-v2/ast/src/__test__/Decorator.test.ts index 1d07efc26e9..a08aeff97a4 100644 --- a/generators/python-v2/codegen/src/ast/__test__/Decorator.test.ts +++ b/generators/python-v2/ast/src/__test__/Decorator.test.ts @@ -1,4 +1,4 @@ -import { python } from "../.."; +import { python } from ".."; describe("Decorator", () => { describe("toString", () => { diff --git a/generators/python-v2/codegen/src/ast/__test__/Field.test.ts b/generators/python-v2/ast/src/__test__/Field.test.ts similarity index 98% rename from generators/python-v2/codegen/src/ast/__test__/Field.test.ts rename to generators/python-v2/ast/src/__test__/Field.test.ts index 4bbfe03fc15..5daff5f6ba9 100644 --- a/generators/python-v2/codegen/src/ast/__test__/Field.test.ts +++ b/generators/python-v2/ast/src/__test__/Field.test.ts @@ -1,4 +1,4 @@ -import { python } from "../.."; +import { python } from ".."; import { Writer } from "../core/Writer"; describe("Field", () => { diff --git a/generators/python-v2/codegen/src/ast/__test__/Method.test.ts b/generators/python-v2/ast/src/__test__/Method.test.ts similarity index 97% rename from generators/python-v2/codegen/src/ast/__test__/Method.test.ts rename to generators/python-v2/ast/src/__test__/Method.test.ts index 70f6e405456..2e46f51d6ff 100644 --- a/generators/python-v2/codegen/src/ast/__test__/Method.test.ts +++ b/generators/python-v2/ast/src/__test__/Method.test.ts @@ -1,7 +1,5 @@ import { ClassMethodType } from "../Method"; -import { Type } from "../Type"; -import { CodeBlock } from "../CodeBlock"; -import { python } from "../.."; +import { python } from ".."; import { Writer } from "../core/Writer"; describe("Method", () => { @@ -158,7 +156,7 @@ describe("Method", () => { }); childMethod.addStatement(python.codeBlock("self.parent_method()")); childMethod.addStatement(python.codeBlock('return "Child method called"')); - childClassDef.addStatement(childMethod); + childClassDef.add(childMethod); method.addStatement(childClassDef); method.addStatement(python.codeBlock("return ChildClass()")); diff --git a/generators/python-v2/codegen/src/ast/__test__/MethodInvocation.test.ts b/generators/python-v2/ast/src/__test__/MethodInvocation.test.ts similarity index 97% rename from generators/python-v2/codegen/src/ast/__test__/MethodInvocation.test.ts rename to generators/python-v2/ast/src/__test__/MethodInvocation.test.ts index 1de8df3d93e..b05fe88b285 100644 --- a/generators/python-v2/codegen/src/ast/__test__/MethodInvocation.test.ts +++ b/generators/python-v2/ast/src/__test__/MethodInvocation.test.ts @@ -1,6 +1,5 @@ -import { MethodInvocation } from "../MethodInvocation"; import { Writer } from "../core/Writer"; -import { python } from "../.."; +import { python } from ".."; describe("MethodInvocation", () => { let writer: Writer; diff --git a/generators/python-v2/codegen/src/ast/__test__/Operator.test.ts b/generators/python-v2/ast/src/__test__/Operator.test.ts similarity index 98% rename from generators/python-v2/codegen/src/ast/__test__/Operator.test.ts rename to generators/python-v2/ast/src/__test__/Operator.test.ts index 54dd92dd8d7..d2f741b88e0 100644 --- a/generators/python-v2/codegen/src/ast/__test__/Operator.test.ts +++ b/generators/python-v2/ast/src/__test__/Operator.test.ts @@ -1,4 +1,4 @@ -import { python } from "../.."; +import { python } from ".."; import { Writer } from "../core/Writer"; import { OperatorType } from "../OperatorType"; diff --git a/generators/python-v2/codegen/src/ast/__test__/PythonFile.test.ts b/generators/python-v2/ast/src/__test__/PythonFile.test.ts similarity index 96% rename from generators/python-v2/codegen/src/ast/__test__/PythonFile.test.ts rename to generators/python-v2/ast/src/__test__/PythonFile.test.ts index d576d6a1eff..914ee9b461f 100644 --- a/generators/python-v2/codegen/src/ast/__test__/PythonFile.test.ts +++ b/generators/python-v2/ast/src/__test__/PythonFile.test.ts @@ -1,10 +1,7 @@ -import { python } from "../../../src"; +import { python } from ".."; import { Writer } from "../core/Writer"; -import { Reference } from "../Reference"; -import { Class } from "../Class"; import { Method } from "../Method"; import { CodeBlock } from "../CodeBlock"; -import { Type } from "../Type"; describe("PythonFile", () => { let writer: Writer; @@ -38,7 +35,7 @@ describe("PythonFile", () => { name: "TestClass" }); testClass.addReference(python.reference({ modulePath: ["itertools"], name: "chain" })); - testClass.addStatement(python.codeBlock("flat_list = list(itertools.chain([[1, 2], [3, 4]]))")); + testClass.add(python.codeBlock("flat_list = list(itertools.chain([[1, 2], [3, 4]]))")); file.addStatement(testClass); diff --git a/generators/python-v2/codegen/src/ast/__test__/Reference.test.ts b/generators/python-v2/ast/src/__test__/Reference.test.ts similarity index 99% rename from generators/python-v2/codegen/src/ast/__test__/Reference.test.ts rename to generators/python-v2/ast/src/__test__/Reference.test.ts index 7d1e3ddda76..d9311c1ed07 100644 --- a/generators/python-v2/codegen/src/ast/__test__/Reference.test.ts +++ b/generators/python-v2/ast/src/__test__/Reference.test.ts @@ -1,4 +1,4 @@ -import { python } from "../.."; +import { python } from ".."; import { Writer } from "../core/Writer"; describe("Reference", () => { diff --git a/generators/python-v2/codegen/src/ast/__test__/Type.test.ts b/generators/python-v2/ast/src/__test__/Type.test.ts similarity index 98% rename from generators/python-v2/codegen/src/ast/__test__/Type.test.ts rename to generators/python-v2/ast/src/__test__/Type.test.ts index c29d4bda9f1..079b3efc4e8 100644 --- a/generators/python-v2/codegen/src/ast/__test__/Type.test.ts +++ b/generators/python-v2/ast/src/__test__/Type.test.ts @@ -1,5 +1,4 @@ -import { python } from "../.."; -import { Reference } from "../Reference"; +import { python } from ".."; import { Type } from "../Type"; import { Writer } from "../core/Writer"; diff --git a/generators/python-v2/codegen/src/ast/__test__/TypeInstantiation.test.ts b/generators/python-v2/ast/src/__test__/TypeInstantiation.test.ts similarity index 99% rename from generators/python-v2/codegen/src/ast/__test__/TypeInstantiation.test.ts rename to generators/python-v2/ast/src/__test__/TypeInstantiation.test.ts index 0e36509083e..d391c567b08 100644 --- a/generators/python-v2/codegen/src/ast/__test__/TypeInstantiation.test.ts +++ b/generators/python-v2/ast/src/__test__/TypeInstantiation.test.ts @@ -1,6 +1,6 @@ import { TypeInstantiation } from "../TypeInstantiation"; import { Writer } from "../core/Writer"; -import { python } from "../.."; +import { python } from ".."; describe("TypeInstantiation", () => { let writer: Writer; diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/Class.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/Class.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/Class.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/Class.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/ClassInstantiation.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/ClassInstantiation.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/ClassInstantiation.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/ClassInstantiation.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/CodeBlock.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/CodeBlock.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/CodeBlock.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/CodeBlock.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/Decorator.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/Decorator.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/Decorator.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/Decorator.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/Field.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/Field.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/Field.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/Field.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/Method.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/Method.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/Method.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/Method.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/MethodInvocation.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/MethodInvocation.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/MethodInvocation.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/MethodInvocation.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/Operator.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/Operator.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/Operator.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/Operator.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/PythonFile.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/PythonFile.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/PythonFile.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/PythonFile.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/Reference.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/Reference.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/Reference.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/Reference.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/Type.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/Type.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/Type.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/Type.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/__test__/__snapshots__/TypeInstantiation.test.ts.snap b/generators/python-v2/ast/src/__test__/__snapshots__/TypeInstantiation.test.ts.snap similarity index 100% rename from generators/python-v2/codegen/src/ast/__test__/__snapshots__/TypeInstantiation.test.ts.snap rename to generators/python-v2/ast/src/__test__/__snapshots__/TypeInstantiation.test.ts.snap diff --git a/generators/python-v2/codegen/src/ast/core/AstNode.ts b/generators/python-v2/ast/src/core/AstNode.ts similarity index 78% rename from generators/python-v2/codegen/src/ast/core/AstNode.ts rename to generators/python-v2/ast/src/core/AstNode.ts index 6400693e471..a28e3adc6ad 100644 --- a/generators/python-v2/codegen/src/ast/core/AstNode.ts +++ b/generators/python-v2/ast/src/core/AstNode.ts @@ -1,7 +1,6 @@ import { AbstractAstNode } from "@fern-api/generator-commons"; import { Writer } from "./Writer"; -import init, { Config, format } from "@wasm-fmt/ruff_fmt"; -import type { Reference } from "../Reference"; +import { Reference } from "../Reference"; export abstract class AstNode extends AbstractAstNode { protected references: Reference[] = []; @@ -38,8 +37,9 @@ export abstract class AstNode extends AbstractAstNode { /** * Writes the node to a string and formats it. */ - public async toStringFormatted(config?: Config): Promise { - await init(); - return format(this.toString(), undefined, config); + public async toStringFormatted(): Promise { + const writer = new Writer(); + this.write(writer); + return await writer.toStringFormatted(); } } diff --git a/generators/python-v2/codegen/src/ast/core/Writer.ts b/generators/python-v2/ast/src/core/Writer.ts similarity index 71% rename from generators/python-v2/codegen/src/ast/core/Writer.ts rename to generators/python-v2/ast/src/core/Writer.ts index 5001802b950..f46b42eb19d 100644 --- a/generators/python-v2/codegen/src/ast/core/Writer.ts +++ b/generators/python-v2/ast/src/core/Writer.ts @@ -1,14 +1,17 @@ import { AbstractWriter } from "@fern-api/generator-commons"; -import init, { format } from "@wasm-fmt/ruff_fmt"; export declare namespace Writer {} +/* Dot delimited string where */ +type Module = string; + export class Writer extends AbstractWriter { public toString(): string { return this.buffer; } public async toStringFormatted(): Promise { + const { default: init, format } = await import("@wasm-fmt/ruff_fmt"); await init(); return format(this.buffer); } diff --git a/generators/python-v2/codegen/src/ast/core/types.ts b/generators/python-v2/ast/src/core/types.ts similarity index 100% rename from generators/python-v2/codegen/src/ast/core/types.ts rename to generators/python-v2/ast/src/core/types.ts diff --git a/generators/python-v2/codegen/src/index.ts b/generators/python-v2/ast/src/index.ts similarity index 100% rename from generators/python-v2/codegen/src/index.ts rename to generators/python-v2/ast/src/index.ts diff --git a/generators/python-v2/codegen/src/python.ts b/generators/python-v2/ast/src/python.ts similarity index 51% rename from generators/python-v2/codegen/src/python.ts rename to generators/python-v2/ast/src/python.ts index 45b87739039..67d6795a5c9 100644 --- a/generators/python-v2/codegen/src/python.ts +++ b/generators/python-v2/ast/src/python.ts @@ -1,17 +1,30 @@ -import { - Class, - Field, - Reference, - CodeBlock, - Method, - Parameter, - MethodArgument, - PythonFile, - Decorator, - MethodInvocation, - ClassInstantiation, - Operator -} from "./ast"; +import { Class } from "./Class"; +import { Field } from "./Field"; +import { Reference } from "./Reference"; +import { CodeBlock } from "./CodeBlock"; +import { Method } from "./Method"; +import { MethodInvocation } from "./MethodInvocation"; +import { ClassInstantiation } from "./ClassInstantiation"; +import { Parameter } from "./Parameter"; +import { MethodArgument } from "./MethodArgument"; +import { PythonFile } from "./PythonFile"; +import { Decorator } from "./Decorator"; +import { Operator } from "./Operator"; + +export { Class } from "./Class"; +export { Field } from "./Field"; +export { Reference } from "./Reference"; +export { CodeBlock } from "./CodeBlock"; +export { Method } from "./Method"; +export { MethodInvocation } from "./MethodInvocation"; +export { ClassInstantiation } from "./ClassInstantiation"; +export { Parameter } from "./Parameter"; +export { MethodArgument } from "./MethodArgument"; +export { PythonFile } from "./PythonFile"; +export { Decorator } from "./Decorator"; +export { Operator } from "./Operator"; +export { Type } from "./Type"; +export { TypeInstantiation } from "./TypeInstantiation"; export function file(args: PythonFile.Args): PythonFile { return new PythonFile(args); @@ -60,21 +73,3 @@ export function methodArgument(args: MethodArgument.Args): MethodArgument { export function operator(args: Operator.Args): Operator { return new Operator(args); } - -export { - AstNode, - Class, - Decorator, - Field, - Type, - Writer, - Reference, - CodeBlock, - Method, - TypeInstantiation, - PythonFile, - MethodInvocation, - ClassInstantiation, - Operator, - OperatorType -} from "./ast"; diff --git a/generators/python-v2/codegen/tsconfig.json b/generators/python-v2/ast/tsconfig.json similarity index 100% rename from generators/python-v2/codegen/tsconfig.json rename to generators/python-v2/ast/tsconfig.json diff --git a/generators/python-v2/codegen/vitest.config.ts b/generators/python-v2/ast/vitest.config.ts similarity index 100% rename from generators/python-v2/codegen/vitest.config.ts rename to generators/python-v2/ast/vitest.config.ts diff --git a/generators/python-v2/codegen/.depcheckrc.json b/generators/python-v2/base/.depcheckrc.json similarity index 100% rename from generators/python-v2/codegen/.depcheckrc.json rename to generators/python-v2/base/.depcheckrc.json diff --git a/generators/python-v2/base/.prettierrc.cjs b/generators/python-v2/base/.prettierrc.cjs new file mode 100644 index 00000000000..39cf0d0b8c9 --- /dev/null +++ b/generators/python-v2/base/.prettierrc.cjs @@ -0,0 +1 @@ +module.exports = require("../../../.prettierrc.json"); diff --git a/generators/python-v2/base/package.json b/generators/python-v2/base/package.json new file mode 100644 index 00000000000..748e935dd8b --- /dev/null +++ b/generators/python-v2/base/package.json @@ -0,0 +1,49 @@ +{ + "name": "@fern-api/base-python-generator", + "version": "0.0.0", + "repository": { + "type": "git", + "url": "https://github.com/fern-api/fern.git", + "directory": "generators/pythonv2/codegen" + }, + "files": [ + "lib" + ], + "type": "module", + "source": "src/index.ts", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "sideEffects": false, + "scripts": { + "clean": "rm -rf ./lib && tsc --build --clean", + "compile": "tsc --build", + "test": "vitest --passWithNoTests --run", + "test:update": "vitest --passWithNoTests --run -u", + "lint:eslint": "eslint --max-warnings 0 . --ignore-path=../../../.eslintignore", + "lint:eslint:fix": "yarn lint:eslint --fix", + "format": "prettier --write --ignore-unknown --ignore-path ../../../shared/.prettierignore \"**\"", + "format:check": "prettier --check --ignore-unknown --ignore-path ../../../shared/.prettierignore \"**\"", + "organize-imports": "organize-imports-cli tsconfig.json", + "depcheck": "depcheck" + }, + "dependencies": { + "@fern-api/fs-utils": "workspace:*", + "@fern-api/core-utils": "workspace:*", + "@fern-api/generator-commons": "workspace:*", + "@fern-api/python-ast": "workspace:*", + "@fern-api/logging-execa": "workspace:*", + "@fern-fern/ir-sdk": "53.7.0", + "lodash-es": "^4.17.21", + "zod": "^3.22.4" + }, + "devDependencies": { + "@types/lodash-es": "^4.17.12", + "@types/node": "18.7.18", + "depcheck": "^1.4.6", + "eslint": "^8.56.0", + "organize-imports-cli": "^0.10.0", + "prettier": "^2.7.1", + "typescript": "4.6.4", + "vitest": "^2.0.5" + } +} \ No newline at end of file diff --git a/generators/python-v2/base/src/asIs/core.ts b/generators/python-v2/base/src/asIs/core.ts new file mode 100644 index 00000000000..07531d6c48d --- /dev/null +++ b/generators/python-v2/base/src/asIs/core.ts @@ -0,0 +1,6 @@ +import { python } from "@fern-api/python-ast"; + +export const serialize_datetime = python.reference({ + modulePath: ["core", "datetime_utils"], + name: "serialize_datetime" +}); diff --git a/generators/python-v2/base/src/cli/AbstractPythonGeneratorCli.ts b/generators/python-v2/base/src/cli/AbstractPythonGeneratorCli.ts new file mode 100644 index 00000000000..00f5fffb0e3 --- /dev/null +++ b/generators/python-v2/base/src/cli/AbstractPythonGeneratorCli.ts @@ -0,0 +1,23 @@ +import { AbsoluteFilePath } from "@fern-api/fs-utils"; +import { AbstractGeneratorCli, parseIR } from "@fern-api/generator-commons"; +import { IntermediateRepresentation } from "@fern-fern/ir-sdk/api"; +import * as IrSerialization from "@fern-fern/ir-sdk/serialization"; +import { AbstractPythonGeneratorContext } from "../context/AbstractPythonGeneratorContext"; +import { BasePythonCustomConfigSchema } from "../custom-config/BasePythonCustomConfigSchema"; + +export abstract class AbstractPythonGeneratorCli< + CustomConfig extends BasePythonCustomConfigSchema, + PythonGeneratorContext extends AbstractPythonGeneratorContext +> extends AbstractGeneratorCli { + /** + * Parses the IR for the Python generators + * @param irFilepath + * @returns + */ + protected async parseIntermediateRepresentation(irFilepath: string): Promise { + return await parseIR({ + absolutePathToIR: AbsoluteFilePath.of(irFilepath), + parse: IrSerialization.IntermediateRepresentation.parse + }); + } +} diff --git a/generators/python-v2/base/src/cli/index.ts b/generators/python-v2/base/src/cli/index.ts new file mode 100644 index 00000000000..24e287a7a74 --- /dev/null +++ b/generators/python-v2/base/src/cli/index.ts @@ -0,0 +1,2 @@ +export { AbstractPythonGeneratorContext } from "../context/AbstractPythonGeneratorContext"; +export { AbstractPythonGeneratorCli } from "./AbstractPythonGeneratorCli"; diff --git a/generators/python-v2/base/src/context/AbstractPythonGeneratorContext.ts b/generators/python-v2/base/src/context/AbstractPythonGeneratorContext.ts new file mode 100644 index 00000000000..e8550567007 --- /dev/null +++ b/generators/python-v2/base/src/context/AbstractPythonGeneratorContext.ts @@ -0,0 +1,61 @@ +import { AbstractGeneratorContext, FernGeneratorExec, GeneratorNotificationService } from "@fern-api/generator-commons"; +import { IntermediateRepresentation, Name, TypeDeclaration, TypeId, TypeReference } from "@fern-fern/ir-sdk/api"; +import { snakeCase } from "lodash-es"; +import { BasePythonCustomConfigSchema } from "../custom-config/BasePythonCustomConfigSchema"; +import { PythonProject } from "../project"; +import { PythonTypeMapper } from "./PythonTypeMapper"; + +export abstract class AbstractPythonGeneratorContext< + CustomConfig extends BasePythonCustomConfigSchema +> extends AbstractGeneratorContext { + private packageName: string; + public readonly pythonTypeMapper: PythonTypeMapper; + public readonly project: PythonProject; + + public constructor( + public readonly ir: IntermediateRepresentation, + public readonly config: FernGeneratorExec.config.GeneratorConfig, + public readonly customConfig: CustomConfig, + public readonly generatorNotificationService: GeneratorNotificationService + ) { + super(config, generatorNotificationService); + this.packageName = snakeCase(`${this.config.organization}_${this.ir.apiName.snakeCase.unsafeName}`); + this.pythonTypeMapper = new PythonTypeMapper(this); + this.project = new PythonProject({ context: this }); + } + + public getTypeDeclarationOrThrow(typeId: TypeId): TypeDeclaration { + const typeDeclaration = this.ir.types[typeId]; + if (typeDeclaration == null) { + throw new Error(`Could not find type declaration for type id: ${typeId}`); + } + return typeDeclaration; + } + + public isTypeReferenceOptional(typeReference: TypeReference): boolean { + if (typeReference.type === "container" && typeReference.container.type === "optional") { + return true; + } + if (typeReference.type === "named") { + const typeDeclaration = this.getTypeDeclarationOrThrow(typeReference.typeId); + if (typeDeclaration.shape.type === "alias") { + return this.isTypeReferenceOptional(typeDeclaration.shape.aliasOf); + } + } + return false; + } + + public getClassName(name: Name): string { + return name.pascalCase.safeName; + } + + public getPascalCaseSafeName(name: Name): string { + return name.pascalCase.safeName; + } + + public getSnakeCaseSafeName(name: Name): string { + return name.snakeCase.safeName; + } + + public abstract getModulePathForId(typeId: TypeId): string[]; +} diff --git a/generators/python-v2/base/src/context/PythonTypeMapper.ts b/generators/python-v2/base/src/context/PythonTypeMapper.ts new file mode 100644 index 00000000000..5d3be9393b0 --- /dev/null +++ b/generators/python-v2/base/src/context/PythonTypeMapper.ts @@ -0,0 +1,120 @@ +import { assertNever } from "@fern-api/core-utils"; +import { + ContainerType, + DeclaredTypeName, + Literal, + Name, + PrimitiveType, + PrimitiveTypeV1, + TypeId, + TypeReference +} from "@fern-fern/ir-sdk/api"; +import { BasePythonCustomConfigSchema } from "../custom-config/BasePythonCustomConfigSchema"; +import { AbstractPythonGeneratorContext } from "./AbstractPythonGeneratorContext"; +import { python } from "@fern-api/python-ast"; + +export declare namespace PythonTypeMapper { + interface Args { + reference: TypeReference; + } +} + +export class PythonTypeMapper { + private context: AbstractPythonGeneratorContext; + + constructor(context: AbstractPythonGeneratorContext) { + this.context = context; + } + + public convert({ reference }: PythonTypeMapper.Args): python.Type { + switch (reference.type) { + case "container": + return this.convertContainer({ + container: reference.container + }); + case "named": + return this.convertNamed({ named: reference }); + case "primitive": + return this.convertPrimitive(reference); + case "unknown": + return python.Type.any(); + default: + assertNever(reference); + } + } + + public convertToClassReference({ typeId, name }: { typeId: TypeId; name: Name }): python.Reference { + return new python.Reference({ + name: this.context.getPascalCaseSafeName(name), + modulePath: [...this.context.getModulePathForId(typeId), this.context.getSnakeCaseSafeName(name)] + }); + } + + private convertContainer({ container }: { container: ContainerType }): python.Type { + switch (container.type) { + case "list": + return python.Type.list(this.convert({ reference: container.list })); + case "map": { + const key = this.convert({ reference: container.keyType }); + const value = this.convert({ reference: container.valueType }); + return python.Type.dict(key, value); + } + case "set": + return python.Type.set(this.convert({ reference: container.set })); + case "optional": + return python.Type.optional(this.convert({ reference: container.optional })); + case "literal": + return this.convertLiteral({ literal: container.literal }); + default: + assertNever(container); + } + } + + private convertPrimitive({ primitive }: { primitive: PrimitiveType }): python.Type { + return PrimitiveTypeV1._visit(primitive.v1, { + integer: () => python.Type.int(), + long: () => python.Type.int(), + uint: () => python.Type.int(), + uint64: () => python.Type.int(), + float: () => python.Type.float(), + double: () => python.Type.float(), + boolean: () => python.Type.bool(), + string: () => python.Type.str(), + date: () => python.Type.str(), + dateTime: () => python.Type.datetime(), + uuid: () => python.Type.uuid(), + base64: () => python.Type.bytes(), + bigInteger: () => python.Type.str(), + _other: () => python.Type.any() + }); + } + + private convertLiteral({ literal }: { literal: Literal }): python.Type { + switch (literal.type) { + case "boolean": + return python.Type.bool(); + case "string": + return python.Type.str(); + } + } + + private convertNamed({ named }: { named: DeclaredTypeName }): python.Type { + const objectClassReference = this.convertToClassReference(named); + const typeDeclaration = this.context.getTypeDeclarationOrThrow(named.typeId); + switch (typeDeclaration.shape.type) { + case "alias": + return this.convert({ reference: typeDeclaration.shape.aliasOf }); + case "enum": + return python.Type.reference(objectClassReference); + case "object": + return python.Type.reference(objectClassReference); + case "union": + return python.Type.reference(objectClassReference); + case "undiscriminatedUnion": { + return python.Type.reference(objectClassReference); + } + default: + assertNever(typeDeclaration.shape); + } + } +} diff --git a/generators/python-v2/base/src/context/index.ts b/generators/python-v2/base/src/context/index.ts new file mode 100644 index 00000000000..785d90a9f34 --- /dev/null +++ b/generators/python-v2/base/src/context/index.ts @@ -0,0 +1,2 @@ +export { AbstractPythonGeneratorContext } from "./AbstractPythonGeneratorContext"; +export { PythonTypeMapper } from "./PythonTypeMapper"; diff --git a/generators/python-v2/base/src/custom-config/BasePythonCustomConfigSchema.ts b/generators/python-v2/base/src/custom-config/BasePythonCustomConfigSchema.ts new file mode 100644 index 00000000000..3ca1ad3a695 --- /dev/null +++ b/generators/python-v2/base/src/custom-config/BasePythonCustomConfigSchema.ts @@ -0,0 +1,5 @@ +import { z } from "zod"; + +export const BasePythonCustomConfigSchema = z.object({}); + +export type BasePythonCustomConfigSchema = z.infer; diff --git a/generators/python-v2/base/src/custom-config/index.ts b/generators/python-v2/base/src/custom-config/index.ts new file mode 100644 index 00000000000..ee97842c713 --- /dev/null +++ b/generators/python-v2/base/src/custom-config/index.ts @@ -0,0 +1 @@ +export { BasePythonCustomConfigSchema } from "./BasePythonCustomConfigSchema"; diff --git a/generators/python-v2/base/src/dependencies/dt.ts b/generators/python-v2/base/src/dependencies/dt.ts new file mode 100644 index 00000000000..fff1855c1f5 --- /dev/null +++ b/generators/python-v2/base/src/dependencies/dt.ts @@ -0,0 +1,6 @@ +import { python } from "@fern-api/python-ast"; + +export const datetime = python.reference({ + name: "datetime", + modulePath: ["dt"] +}); diff --git a/generators/python-v2/base/src/dependencies/pydantic.ts b/generators/python-v2/base/src/dependencies/pydantic.ts new file mode 100644 index 00000000000..fd82df294b7 --- /dev/null +++ b/generators/python-v2/base/src/dependencies/pydantic.ts @@ -0,0 +1,18 @@ +import { python } from "@fern-api/python-ast"; + +export const BaseModel = python.reference({ + name: "BaseModel", + modulePath: ["pydantic"] +}); + +export const Field = python.reference({ + name: "Field", + modulePath: ["pydantic"] +}); + +export const RootModel = (type: python.Type): python.Reference => + python.reference({ + name: "RootModel", + modulePath: ["pydantic"], + genericTypes: [type] + }); diff --git a/generators/python-v2/base/src/index.ts b/generators/python-v2/base/src/index.ts new file mode 100644 index 00000000000..99d94b063b7 --- /dev/null +++ b/generators/python-v2/base/src/index.ts @@ -0,0 +1,7 @@ +export * from "./context"; +export * from "./project"; +export * from "./custom-config"; +export * from "./cli"; +export * as dt from "./dependencies/dt"; +export * as pydantic from "./dependencies/pydantic"; +export * as core from "./asIs/core"; diff --git a/generators/python-v2/base/src/project/PythonProject.ts b/generators/python-v2/base/src/project/PythonProject.ts new file mode 100644 index 00000000000..86f2fde9c36 --- /dev/null +++ b/generators/python-v2/base/src/project/PythonProject.ts @@ -0,0 +1,31 @@ +import { AbstractProject } from "@fern-api/generator-commons"; +import { AbstractPythonGeneratorContext } from "../cli"; +import { BasePythonCustomConfigSchema } from "../custom-config"; +import { WriteablePythonFile } from "./WriteablePythonFile"; +import { loggingExeca } from "@fern-api/logging-execa"; + +/** + * In memory representation of a Python project. + */ +export class PythonProject extends AbstractProject> { + private sourceFiles: WriteablePythonFile[] = []; + + public constructor({ context }: { context: AbstractPythonGeneratorContext }) { + super(context); + } + + public addSourceFiles(file: WriteablePythonFile): void { + this.sourceFiles.push(file); + } + + public async persist(): Promise { + await Promise.all( + this.sourceFiles.map(async (file) => { + return await file.write(this.absolutePathToOutputDirectory); + }) + ); + await loggingExeca(undefined, "ruff", ["format", "."], { + cwd: this.absolutePathToOutputDirectory + }); + } +} diff --git a/generators/python-v2/base/src/project/WriteablePythonFile.ts b/generators/python-v2/base/src/project/WriteablePythonFile.ts new file mode 100644 index 00000000000..2bd99a70c2b --- /dev/null +++ b/generators/python-v2/base/src/project/WriteablePythonFile.ts @@ -0,0 +1,23 @@ +import { AbsoluteFilePath, RelativeFilePath } from "@fern-api/fs-utils"; +import { File } from "@fern-api/generator-commons"; +import { python } from "@fern-api/python-ast"; + +export declare namespace WriteablePythonFile { + interface Args { + filename: string; + /* Directory of the filepath */ + directory: RelativeFilePath; + + contents: python.PythonFile; + } +} + +export class WriteablePythonFile extends File { + constructor({ filename, directory, contents }: WriteablePythonFile.Args) { + super(`${filename}.py`, directory, contents.toString()); + } + + public async tryWrite(directoryPrefix: AbsoluteFilePath): Promise { + await this.write(directoryPrefix); + } +} diff --git a/generators/python-v2/base/src/project/index.ts b/generators/python-v2/base/src/project/index.ts new file mode 100644 index 00000000000..b61fe467824 --- /dev/null +++ b/generators/python-v2/base/src/project/index.ts @@ -0,0 +1,2 @@ +export { WriteablePythonFile } from "./WriteablePythonFile"; +export { PythonProject } from "./PythonProject"; diff --git a/generators/python-v2/base/tsconfig.json b/generators/python-v2/base/tsconfig.json new file mode 100644 index 00000000000..71c717c3d69 --- /dev/null +++ b/generators/python-v2/base/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../../shared/tsconfig.shared.json", + "compilerOptions": { "composite": true, "outDir": "lib", "rootDir": "src" }, + "include": ["./src/**/*"], + "references": [ + { "path": "../../../packages/commons/core-utils" }, + { "path": "../../../packages/commons/fs-utils" }, + { "path": "../../../packages/commons/logging-execa" }, + { "path": "../../commons" }, + { "path": "../ast" }, + { "path": "../../../packages/commons/logging-execa" } + ] +} diff --git a/generators/python-v2/base/vitest.config.ts b/generators/python-v2/base/vitest.config.ts new file mode 100644 index 00000000000..fecc099c58a --- /dev/null +++ b/generators/python-v2/base/vitest.config.ts @@ -0,0 +1 @@ +export { default } from "../../../shared/vitest.config"; diff --git a/generators/python-v2/codegen/src/ast/index.ts b/generators/python-v2/codegen/src/ast/index.ts deleted file mode 100644 index fc501ca9734..00000000000 --- a/generators/python-v2/codegen/src/ast/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -export { Class } from "./Class"; -export { Field } from "./Field"; -export { Writer } from "./core/Writer"; -export { Type } from "./Type"; -export { Reference } from "./Reference"; -export { CodeBlock } from "./CodeBlock"; -export { AstNode } from "./core/AstNode"; -export { Method } from "./Method"; -export { MethodInvocation } from "./MethodInvocation"; -export { ClassInstantiation } from "./ClassInstantiation"; -export { Parameter } from "./Parameter"; -export { MethodArgument } from "./MethodArgument"; -export { PythonFile } from "./PythonFile"; -export { Decorator } from "./Decorator"; -export { TypeInstantiation } from "./TypeInstantiation"; -export { Operator } from "./Operator"; -export { OperatorType } from "./OperatorType"; diff --git a/generators/python-v2/fastapi/tsconfig.json b/generators/python-v2/fastapi/tsconfig.json index 945efb0f393..5c1e319cac3 100644 --- a/generators/python-v2/fastapi/tsconfig.json +++ b/generators/python-v2/fastapi/tsconfig.json @@ -6,6 +6,7 @@ { "path": "../../../packages/commons/core-utils" }, { "path": "../../../packages/commons/fs-utils" }, { "path": "../../commons" }, - { "path": "../codegen" } + { "path": "../ast" }, + { "path": "../base" } ] } diff --git a/generators/python-v2/pydantic-model/Dockerfile b/generators/python-v2/pydantic-model/Dockerfile index 07851f423ae..b6899996cca 100644 --- a/generators/python-v2/pydantic-model/Dockerfile +++ b/generators/python-v2/pydantic-model/Dockerfile @@ -1,3 +1,7 @@ -FROM node:18.1.0-alpine +FROM node:lts-slim +RUN apt-get update && apt-get install -y curl +RUN curl -LsSf https://astral.sh/ruff/install.sh | sh +ENV PATH="/root/.cargo/bin:${PATH}" +RUN ruff --version COPY generators/python-v2/pydantic-model/dist /dist ENTRYPOINT ["node", "/dist/cli.cjs"] diff --git a/generators/python-v2/pydantic-model/build.cjs b/generators/python-v2/pydantic-model/build.cjs new file mode 100644 index 00000000000..63282b4b22f --- /dev/null +++ b/generators/python-v2/pydantic-model/build.cjs @@ -0,0 +1,18 @@ +const packageJson = require("./package.json"); +const tsup = require('tsup'); +const { writeFile, rename } = require("fs/promises"); +const path = require("path"); + +main(); + +async function main() { + await tsup.build({ + entry: ['src/**/*.ts', '!src/__test__'], + format: ['cjs'], + clean: true, + outDir: 'dist', + external: [ + "@wasm-fmt/ruff_fmt", + ], + }); +} \ No newline at end of file diff --git a/generators/python-v2/pydantic-model/build.tsconfig.json b/generators/python-v2/pydantic-model/build.tsconfig.json new file mode 100644 index 00000000000..6a461575e21 --- /dev/null +++ b/generators/python-v2/pydantic-model/build.tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../../shared/tsconfig.shared.json", + "include": ["src/**/*.ts"], + "exclude": ["src/**/__test__"] +} diff --git a/generators/python-v2/pydantic-model/package.json b/generators/python-v2/pydantic-model/package.json index c53dd59affa..a35562fa59d 100644 --- a/generators/python-v2/pydantic-model/package.json +++ b/generators/python-v2/pydantic-model/package.json @@ -25,11 +25,19 @@ "format:check": "prettier --check --ignore-unknown --ignore-path ../../../shared/.prettierignore \"**\"", "organize-imports": "organize-imports-cli tsconfig.json", "depcheck": "depcheck", - "dist:cli": "pnpm compile && tsup ./src/cli.ts --format cjs", + "dist:cli": "pnpm compile && node build.cjs", "publish:cli": "pnpm dist:cli && cd dist && yarn npm publish", "dockerTagLatest": "pnpm dist:cli && docker build -f ./Dockerfile -t fernapi/fern-pydantic-model-v2:latest ../../.." }, "devDependencies": { + "@fern-api/core-utils": "workspace:*", + "@fern-api/base-python-generator": "workspace:*", + "@fern-api/python-ast": "workspace:*", + "@fern-fern/generator-exec-sdk": "^0.0.898", + "zod": "^3.22.4", + "@fern-fern/ir-sdk": "53.7.0", + "@fern-api/fs-utils": "workspace:*", + "@fern-api/generator-commons": "workspace:*", "@types/node": "18.7.18", "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.14", "depcheck": "^1.4.6", diff --git a/generators/python-v2/pydantic-model/src/ModelCustomConfig.ts b/generators/python-v2/pydantic-model/src/ModelCustomConfig.ts new file mode 100644 index 00000000000..c26a5256ef1 --- /dev/null +++ b/generators/python-v2/pydantic-model/src/ModelCustomConfig.ts @@ -0,0 +1,9 @@ +import { z } from "zod"; + +export const PydanticModelCustomConfigSchema = z.object({ + include_union_utils: z.optional(z.boolean()), + version: z.optional(z.enum(["both", "v1", "v2"])), + include_validators: z.optional(z.boolean()) +}); + +export type PydanticModelCustomConfigSchema = z.infer; diff --git a/generators/python-v2/pydantic-model/src/ModelGeneratorCli.ts b/generators/python-v2/pydantic-model/src/ModelGeneratorCli.ts new file mode 100644 index 00000000000..1abb5f9b548 --- /dev/null +++ b/generators/python-v2/pydantic-model/src/ModelGeneratorCli.ts @@ -0,0 +1,53 @@ +import { AbstractPythonGeneratorCli } from "@fern-api/base-python-generator"; +import { FernGeneratorExec } from "@fern-fern/generator-exec-sdk"; +import { IntermediateRepresentation } from "@fern-fern/ir-sdk/api"; +import { PydanticModelCustomConfigSchema } from "./ModelCustomConfig"; +import { PydanticModelGeneratorContext } from "./ModelGeneratorContext"; +import { generateV2Models } from "./v2/generateV2Models"; +import { GeneratorNotificationService } from "@fern-api/generator-commons"; + +export class ModelGeneratorCLI extends AbstractPythonGeneratorCli< + PydanticModelCustomConfigSchema, + PydanticModelGeneratorContext +> { + protected constructContext({ + ir, + customConfig, + generatorConfig, + generatorNotificationService + }: { + ir: IntermediateRepresentation; + customConfig: PydanticModelCustomConfigSchema; + generatorConfig: FernGeneratorExec.GeneratorConfig; + generatorNotificationService: GeneratorNotificationService; + }): PydanticModelGeneratorContext { + return new PydanticModelGeneratorContext(ir, generatorConfig, customConfig, generatorNotificationService); + } + + protected parseCustomConfigOrThrow(customConfig: unknown): PydanticModelCustomConfigSchema { + const parsed = customConfig != null ? PydanticModelCustomConfigSchema.parse(customConfig) : undefined; + if (parsed != null) { + return parsed; + } + return {}; + } + + protected async writeForDownload(context: PydanticModelGeneratorContext): Promise { + return await this.generate(context); + } + + protected async generate(context: PydanticModelGeneratorContext): Promise { + const files = generateV2Models({ context }); + for (const file of files) { + context.project.addSourceFiles(file); + } + await context.project.persist(); + } + + protected publishPackage(context: PydanticModelGeneratorContext): Promise { + throw new Error("Method not implemented."); + } + protected writeForGithub(context: PydanticModelGeneratorContext): Promise { + throw new Error("Method not implemented."); + } +} diff --git a/generators/python-v2/pydantic-model/src/ModelGeneratorContext.ts b/generators/python-v2/pydantic-model/src/ModelGeneratorContext.ts new file mode 100644 index 00000000000..7133e94d1da --- /dev/null +++ b/generators/python-v2/pydantic-model/src/ModelGeneratorContext.ts @@ -0,0 +1,10 @@ +import { AbstractPythonGeneratorContext } from "@fern-api/base-python-generator"; +import { PydanticModelCustomConfigSchema } from "./ModelCustomConfig"; + +export class PydanticModelGeneratorContext extends AbstractPythonGeneratorContext { + public getModulePathForId(typeId: string): string[] { + const typeDeclaration = super.getTypeDeclarationOrThrow(typeId); + const fernFilepath = typeDeclaration.name.fernFilepath; + return [...fernFilepath.allParts.flatMap((part) => ["resources", super.getSnakeCaseSafeName(part)]), "types"]; + } +} diff --git a/generators/python-v2/pydantic-model/src/cli.ts b/generators/python-v2/pydantic-model/src/cli.ts index f01677eeca1..30174f71d0d 100644 --- a/generators/python-v2/pydantic-model/src/cli.ts +++ b/generators/python-v2/pydantic-model/src/cli.ts @@ -1,6 +1,7 @@ +import { ModelGeneratorCLI } from "./ModelGeneratorCli"; + void runCli(); export async function runCli(): Promise { - // eslint-disable-next-line no-console - console.log("Noop..."); + await new ModelGeneratorCLI().run(); } diff --git a/generators/python-v2/pydantic-model/src/v2/ObjectGenerator.ts b/generators/python-v2/pydantic-model/src/v2/ObjectGenerator.ts new file mode 100644 index 00000000000..fa4a8e60a30 --- /dev/null +++ b/generators/python-v2/pydantic-model/src/v2/ObjectGenerator.ts @@ -0,0 +1,152 @@ +import { WriteablePythonFile, pydantic, core, dt } from "@fern-api/base-python-generator"; +import { python } from "@fern-api/python-ast"; +import { NameAndWireValue, ObjectTypeDeclaration, TypeDeclaration, TypeId } from "@fern-fern/ir-sdk/api"; +import { PydanticModelGeneratorContext } from "../ModelGeneratorContext"; +import { RelativeFilePath } from "@fern-api/fs-utils"; + +export class ObjectGenerator { + constructor( + private readonly typeId: TypeId, + private readonly context: PydanticModelGeneratorContext, + private readonly typeDeclaration: TypeDeclaration, + private readonly objectDeclaration: ObjectTypeDeclaration + ) {} + + public doGenerate(): WriteablePythonFile { + const class_ = python.class_({ + name: this.context.getPascalCaseSafeName(this.typeDeclaration.name.name), + docs: this.typeDeclaration.docs, + extends_: [ + pydantic.BaseModel, + ...this.objectDeclaration.extends.map((extend) => { + return this.context.pythonTypeMapper.convertToClassReference({ + typeId: extend.typeId, + name: extend.name + }); + }) + ], + decorators: [] + }); + + for (const property of this.objectDeclaration.properties) { + const propertyName = this.getPropertyName({ + className: this.context.getPascalCaseSafeName(this.typeDeclaration.name.name), + objectProperty: property.name + }); + + const propertyType = this.context.pythonTypeMapper.convert({ reference: property.valueType }); + + const value = this.context.isTypeReferenceOptional(property.valueType) + ? python.codeBlock("None") + : undefined; + + const wireValue = propertyName === property.name.wireValue ? undefined : property.name.wireValue; + + let initializer = undefined; + + if (value != null && wireValue == null) { + initializer = value; + } else if (wireValue != null || value != null) { + // TODO(dsinghvi): uncomment after redoing imports + python.codeBlock((writer) => { + const arguments_: python.MethodArgument[] = []; + if (wireValue != null) { + arguments_.push( + python.methodArgument({ + name: "alias", + value: python.codeBlock(`"${wireValue}"`) + }) + ); + } + if (value != null) { + arguments_.push( + python.methodArgument({ + name: "default", + value + }) + ); + } + // writer.writeNode( + // python.instantiateClass({ + // classReference: pydantic.Field, + // arguments_ + // }) + // ); + }); + } + + class_.addField( + python.field({ + name: propertyName, + type: propertyType, + docs: property.docs, + initializer + }) + ); + } + + class_.add(this.getConfigClass()); + + const module = this.context.getModulePathForId(this.typeId); + const filename = this.context.getSnakeCaseSafeName(this.typeDeclaration.name.name); + const file = python.file({ + moduleName: module.join("."), + path: ["test"], + name: filename + }); + file.addStatement(class_); + + return new WriteablePythonFile({ + contents: file, + directory: RelativeFilePath.of(module.join("/")), + filename + }); + } + + /** + * Class Names and Property Names cannot overlap in C# otherwise there are compilation errors. + */ + private getPropertyName({ + className, + objectProperty + }: { + className: string; + objectProperty: NameAndWireValue; + }): string { + return this.context.getSnakeCaseSafeName(objectProperty.name); + } + + private getConfigClass(): python.Class { + const configClass = python.class_({ + name: "Config" + }); + + configClass.addField( + python.field({ + name: "frozen", + initializer: python.TypeInstantiation.bool(true) + }) + ); + + configClass.addField( + python.field({ + name: "smart_union", + initializer: python.TypeInstantiation.bool(true) + }) + ); + + configClass.addField( + python.field({ + name: "json_encoders", + initializer: python.TypeInstantiation.dict([ + { + key: dt.datetime, + value: core.serialize_datetime + } + ]) + }) + ); + + return configClass; + } +} diff --git a/generators/python-v2/pydantic-model/src/v2/WrappedAliasGenerator.ts b/generators/python-v2/pydantic-model/src/v2/WrappedAliasGenerator.ts new file mode 100644 index 00000000000..966491291c8 --- /dev/null +++ b/generators/python-v2/pydantic-model/src/v2/WrappedAliasGenerator.ts @@ -0,0 +1,261 @@ +import { WriteablePythonFile, pydantic, core, dt } from "@fern-api/base-python-generator"; +import { python } from "@fern-api/python-ast"; +import { AliasTypeDeclaration, PrimitiveTypeV1, TypeDeclaration, TypeId, TypeReference } from "@fern-fern/ir-sdk/api"; +import { PydanticModelGeneratorContext } from "../ModelGeneratorContext"; +import { RelativeFilePath } from "@fern-api/fs-utils"; +import { assertNever } from "@fern-api/core-utils"; + +export class WrappedAliasGenerator { + private readonly className: string; + + constructor( + private readonly typeId: TypeId, + private readonly context: PydanticModelGeneratorContext, + private readonly typeDeclaration: TypeDeclaration, + private readonly aliasDeclaration: AliasTypeDeclaration + ) { + this.className = this.context.getClassName(this.typeDeclaration.name.name); + } + + public doGenerate(): WriteablePythonFile { + const valueType = this.context.pythonTypeMapper.convert({ reference: this.aliasDeclaration.aliasOf }); + + const class_ = python.class_({ + name: this.className, + docs: this.typeDeclaration.docs, + extends_: [pydantic.RootModel(valueType)], + decorators: [] + }); + + class_.addField( + python.field({ + name: "root", + type: valueType, + docs: undefined, + initializer: undefined + }) + ); + + class_.add(this.getGetterMethod()); + + class_.add(this.getBuilderMethod()); + + class_.add(this.getConfigClass()); + + const module = this.context.getModulePathForId(this.typeId); + const filename = this.context.getSnakeCaseSafeName(this.typeDeclaration.name.name); + const file = python.file({ + moduleName: module.join("."), + path: ["test"], + name: filename + }); + file.addStatement(class_); + + return new WriteablePythonFile({ + contents: file, + directory: RelativeFilePath.of(module.join("/")), + filename + }); + } + + private getConfigClass(): python.Class { + const configClass = python.class_({ + name: "Config" + }); + + configClass.addField( + python.field({ + name: "frozen", + initializer: python.TypeInstantiation.bool(true) + }) + ); + + configClass.addField( + python.field({ + name: "smart_union", + initializer: python.TypeInstantiation.bool(true) + }) + ); + + configClass.addField( + python.field({ + name: "json_encoders", + initializer: python.TypeInstantiation.dict([ + { + key: dt.datetime, + value: core.serialize_datetime + } + ]) + }) + ); + + return configClass; + } + + private getGetterMethod(): python.Method { + const method = python.method({ + name: this.getGetterName(this.aliasDeclaration.aliasOf), + return_: python.Type.uuid() + }); + method.addStatement(python.codeBlock("return self.root")); + return method; + } + + private getGetterName(typeReference: TypeReference): string { + return typeReference._visit({ + container: (container) => + container._visit({ + list: () => "get_as_list", + map: () => "get_as_map", + set: () => "get_as_set", + optional: (opt) => this.getGetterName(opt), + literal: () => "get_as_string", + _other: () => "get_value" + }), + named: (typeName) => "get_as_" + typeName.name.snakeCase.unsafeName, + primitive: (primitive) => { + if (primitive.v2 != null) { + return primitive.v2?._visit({ + integer: () => "get_as_int", + double: () => "get_as_float", + string: () => "get_as_str", + boolean: () => "get_as_bool", + long: () => "get_as_int", + dateTime: () => "get_as_datetime", + date: () => "get_as_date", + uuid: () => "get_as_uuid", + base64: () => "get_as_str", + bigInteger: () => "get_as_str", + uint: () => "get_as_int", + uint64: () => "get_as_int", + float: () => "get_as_float", + _other: () => "get_value" + }); + } + switch (primitive.v1) { + case PrimitiveTypeV1.Integer: + return "get_as_int"; + case PrimitiveTypeV1.Double: + return "get_as_float"; + case PrimitiveTypeV1.String: + return "get_as_str"; + case PrimitiveTypeV1.Boolean: + return "get_as_bool"; + case PrimitiveTypeV1.Long: + return "get_as_int"; + case PrimitiveTypeV1.DateTime: + return "get_as_datetime"; + case PrimitiveTypeV1.Date: + return "get_as_date"; + case PrimitiveTypeV1.Uuid: + return "get_as_uuid"; + case PrimitiveTypeV1.Base64: + return "get_as_str"; + case PrimitiveTypeV1.BigInteger: + return "get_as_str"; + case PrimitiveTypeV1.Uint: + return "get_as_int"; + case PrimitiveTypeV1.Uint64: + return "get_as_int"; + case PrimitiveTypeV1.Float: + return "get_as_float"; + default: + assertNever(primitive.v1); + } + }, + unknown: () => "get_value", + _other: () => "get_value" + }); + } + + private getBuilderMethod(): python.Method { + const method = python.method({ + name: this.getBuilderName(this.aliasDeclaration.aliasOf), + static_: true, + parameters: [ + python.parameter({ + name: "value", + type: this.context.pythonTypeMapper.convert({ reference: this.aliasDeclaration.aliasOf }) + }) + ], + return_: python.Type.reference( + new python.Reference({ + name: this.className + }) + ) + }); + method.addStatement( + python.codeBlock((writer) => { + writer.write(`${this.className}(root=value)`); + }) + ); + return method; + } + + private getBuilderName(typeReference: TypeReference): string { + return typeReference._visit({ + container: (container) => + container._visit({ + list: () => "from_list", + map: () => "from_map", + set: () => "from_set", + optional: (opt) => this.getBuilderName(opt), + literal: () => "from_string", + _other: () => "from_value" + }), + named: (typeName) => "from_" + typeName.name.snakeCase.unsafeName, + primitive: (primitive) => { + if (primitive.v2 != null) { + return primitive.v2?._visit({ + integer: () => "from_int", + double: () => "from_float", + string: () => "from_str", + boolean: () => "from_bool", + long: () => "from_int", + dateTime: () => "from_datetime", + date: () => "from_date", + uuid: () => "from_uuid", + base64: () => "from_str", + bigInteger: () => "from_str", + uint: () => "from_int", + uint64: () => "from_int", + float: () => "from_float", + _other: () => "from_value" + }); + } + switch (primitive.v1) { + case PrimitiveTypeV1.Integer: + return "from_int"; + case PrimitiveTypeV1.Double: + return "from_float"; + case PrimitiveTypeV1.String: + return "from_str"; + case PrimitiveTypeV1.Boolean: + return "from_bool"; + case PrimitiveTypeV1.Long: + return "from_int"; + case PrimitiveTypeV1.DateTime: + return "from_datetime"; + case PrimitiveTypeV1.Date: + return "from_date"; + case PrimitiveTypeV1.Uuid: + return "from_uuid"; + case PrimitiveTypeV1.Base64: + return "from_str"; + case PrimitiveTypeV1.BigInteger: + return "from_str"; + case PrimitiveTypeV1.Uint: + return "from_int"; + case PrimitiveTypeV1.Uint64: + return "from_int"; + case PrimitiveTypeV1.Float: + return "from_float"; + default: + assertNever(primitive.v1); + } + }, + unknown: () => "from_value", + _other: () => "from_value" + }); + } +} diff --git a/generators/python-v2/pydantic-model/src/v2/generateV2Models.ts b/generators/python-v2/pydantic-model/src/v2/generateV2Models.ts new file mode 100644 index 00000000000..967b01b485b --- /dev/null +++ b/generators/python-v2/pydantic-model/src/v2/generateV2Models.ts @@ -0,0 +1,26 @@ +import { WriteablePythonFile } from "@fern-api/base-python-generator"; +import { PydanticModelGeneratorContext } from "../ModelGeneratorContext"; +import { ObjectGenerator } from "./ObjectGenerator"; +import { WrappedAliasGenerator } from "./WrappedAliasGenerator"; + +export function generateV2Models({ context }: { context: PydanticModelGeneratorContext }): WriteablePythonFile[] { + const files: WriteablePythonFile[] = []; + for (const [typeId, typeDeclaration] of Object.entries(context.ir.types)) { + const file = typeDeclaration.shape._visit({ + alias: (aliasTypeDeclaration) => { + return new WrappedAliasGenerator(typeId, context, typeDeclaration, aliasTypeDeclaration).doGenerate(); + }, + enum: () => undefined, + object: (objectTypDeclaration) => { + return new ObjectGenerator(typeId, context, typeDeclaration, objectTypDeclaration).doGenerate(); + }, + undiscriminatedUnion: () => undefined, + union: () => undefined, + _other: () => undefined + }); + if (file != null) { + files.push(file); + } + } + return files; +} diff --git a/generators/python-v2/pydantic-model/tsconfig.json b/generators/python-v2/pydantic-model/tsconfig.json index 945efb0f393..5c1e319cac3 100644 --- a/generators/python-v2/pydantic-model/tsconfig.json +++ b/generators/python-v2/pydantic-model/tsconfig.json @@ -6,6 +6,7 @@ { "path": "../../../packages/commons/core-utils" }, { "path": "../../../packages/commons/fs-utils" }, { "path": "../../commons" }, - { "path": "../codegen" } + { "path": "../ast" }, + { "path": "../base" } ] } diff --git a/package-yml.schema.json b/package-yml.schema.json index 13ef45cc541..b9e815958a3 100644 --- a/package-yml.schema.json +++ b/package-yml.schema.json @@ -2676,26 +2676,6 @@ "type": "null" } ] - }, - "transport": { - "oneOf": [ - { - "$ref": "#/definitions/service.ServiceTransport" - }, - { - "type": "null" - } - ] - }, - "source": { - "oneOf": [ - { - "$ref": "#/definitions/source.SourceSchema" - }, - { - "type": "null" - } - ] } }, "required": [ diff --git a/packages/cli/lazy-fern-workspace/src/fern.schema.json b/packages/cli/lazy-fern-workspace/src/fern.schema.json index 1087d676904..5bf909d0050 100644 --- a/packages/cli/lazy-fern-workspace/src/fern.schema.json +++ b/packages/cli/lazy-fern-workspace/src/fern.schema.json @@ -2656,26 +2656,6 @@ "type": "null" } ] - }, - "transport": { - "oneOf": [ - { - "$ref": "#/definitions/service.ServiceTransport" - }, - { - "type": "null" - } - ] - }, - "source": { - "oneOf": [ - { - "$ref": "#/definitions/source.SourceSchema" - }, - { - "type": "null" - } - ] } }, "required": [ diff --git a/packages/cli/lazy-fern-workspace/src/package-yml.schema.json b/packages/cli/lazy-fern-workspace/src/package-yml.schema.json index 13ef45cc541..b9e815958a3 100644 --- a/packages/cli/lazy-fern-workspace/src/package-yml.schema.json +++ b/packages/cli/lazy-fern-workspace/src/package-yml.schema.json @@ -2676,26 +2676,6 @@ "type": "null" } ] - }, - "transport": { - "oneOf": [ - { - "$ref": "#/definitions/service.ServiceTransport" - }, - { - "type": "null" - } - ] - }, - "source": { - "oneOf": [ - { - "$ref": "#/definitions/source.SourceSchema" - }, - { - "type": "null" - } - ] } }, "required": [ diff --git a/packages/seed/src/commands/test/test-runner/TestRunner.ts b/packages/seed/src/commands/test/test-runner/TestRunner.ts index c6bf2953234..a960c0fb23b 100644 --- a/packages/seed/src/commands/test/test-runner/TestRunner.ts +++ b/packages/seed/src/commands/test/test-runner/TestRunner.ts @@ -197,6 +197,7 @@ export abstract class TestRunner { taskContext.logger.info("Successfully wrote .mock directory..."); } catch (error) { taskContext.logger.error(`Generation failed: ${(error as Error)?.message ?? "Unknown error"}`); + taskContext.logger.error(`${(error as Error)?.stack}`); return { type: "failure", cause: "generation", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd03655d98a..cc19bbec1eb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -828,7 +828,7 @@ importers: specifier: ^3.22.3 version: 3.22.4 - generators/python-v2/codegen: + generators/python-v2/ast: dependencies: '@fern-api/core-utils': specifier: workspace:* @@ -836,9 +836,6 @@ importers: '@fern-api/generator-commons': specifier: workspace:* version: link:../../commons - '@fern-fern/ir-sdk': - specifier: 53.7.0 - version: 53.7.0 '@wasm-fmt/ruff_fmt': specifier: ^0.6.1 version: 0.6.1 @@ -863,7 +860,59 @@ importers: version: 4.6.4 vitest: specifier: ^2.0.5 - version: 2.0.5(@types/node@18.7.18)(jsdom@20.0.3)(sass@1.72.0)(terser@5.31.5) + version: 2.1.4(@types/node@18.7.18)(jsdom@20.0.3)(sass@1.72.0)(terser@5.31.5) + + generators/python-v2/base: + dependencies: + '@fern-api/core-utils': + specifier: workspace:* + version: link:../../../packages/commons/core-utils + '@fern-api/fs-utils': + specifier: workspace:* + version: link:../../../packages/commons/fs-utils + '@fern-api/generator-commons': + specifier: workspace:* + version: link:../../commons + '@fern-api/logging-execa': + specifier: workspace:* + version: link:../../../packages/commons/logging-execa + '@fern-api/python-ast': + specifier: workspace:* + version: link:../ast + '@fern-fern/ir-sdk': + specifier: 53.7.0 + version: 53.7.0 + lodash-es: + specifier: ^4.17.21 + version: 4.17.21 + zod: + specifier: ^3.22.4 + version: 3.23.8 + devDependencies: + '@types/lodash-es': + specifier: ^4.17.12 + version: 4.17.12 + '@types/node': + specifier: 18.7.18 + version: 18.7.18 + depcheck: + specifier: ^1.4.6 + version: 1.4.6 + eslint: + specifier: ^8.56.0 + version: 8.56.0 + organize-imports-cli: + specifier: ^0.10.0 + version: 0.10.0 + prettier: + specifier: ^2.7.1 + version: 2.7.1 + typescript: + specifier: 4.6.4 + version: 4.6.4 + vitest: + specifier: ^2.0.5 + version: 2.1.4(@types/node@18.7.18)(jsdom@20.0.3)(sass@1.72.0)(terser@5.31.5) generators/python-v2/fastapi: devDependencies: @@ -900,6 +949,27 @@ importers: generators/python-v2/pydantic-model: devDependencies: + '@fern-api/base-python-generator': + specifier: workspace:* + version: link:../base + '@fern-api/core-utils': + specifier: workspace:* + version: link:../../../packages/commons/core-utils + '@fern-api/fs-utils': + specifier: workspace:* + version: link:../../../packages/commons/fs-utils + '@fern-api/generator-commons': + specifier: workspace:* + version: link:../../commons + '@fern-api/python-ast': + specifier: workspace:* + version: link:../ast + '@fern-fern/generator-exec-sdk': + specifier: ^0.0.898 + version: 0.0.898 + '@fern-fern/ir-sdk': + specifier: 53.7.0 + version: 53.7.0 '@types/node': specifier: 18.7.18 version: 18.7.18 @@ -930,6 +1000,9 @@ importers: vitest: specifier: ^2.0.5 version: 2.0.5(@types/node@18.7.18)(jsdom@20.0.3)(sass@1.72.0)(terser@5.31.5) + zod: + specifier: ^3.22.4 + version: 3.23.8 generators/ruby/cli: dependencies: diff --git a/seed/pydantic-v2/.gitignore b/seed/pydantic-v2/.gitignore new file mode 100644 index 00000000000..449dda6b668 --- /dev/null +++ b/seed/pydantic-v2/.gitignore @@ -0,0 +1,2 @@ +**/.ruffcache/ + diff --git a/seed/pydantic-v2/alias-extends/.mock/definition/__package__.yml b/seed/pydantic-v2/alias-extends/.mock/definition/__package__.yml new file mode 100644 index 00000000000..b93c9081fd9 --- /dev/null +++ b/seed/pydantic-v2/alias-extends/.mock/definition/__package__.yml @@ -0,0 +1,40 @@ +service: + auth: false + base-path: /extends + endpoints: + extendedInlineRequestBody: + path: /extended-inline-request-body + method: POST + request: + name: InlinedChildRequest + body: + extends: AliasType + properties: + child: string + +types: + AliasType: + type: Parent + examples: + - name: One + value: + parent: Property from the parent + + Parent: + properties: + parent: string + examples: + - name: One + value: + parent: Property from the parent + + Child: + extends: Parent + properties: + child: string + examples: + - name: One + value: + parent: Property from the parent + child: Property from the child + diff --git a/seed/pydantic-v2/alias-extends/.mock/definition/api.yml b/seed/pydantic-v2/alias-extends/.mock/definition/api.yml new file mode 100644 index 00000000000..fe47afdc2d2 --- /dev/null +++ b/seed/pydantic-v2/alias-extends/.mock/definition/api.yml @@ -0,0 +1,2 @@ +name: alias-extends +docs: A Test Definition for extending an alias \ No newline at end of file diff --git a/seed/pydantic-v2/alias-extends/.mock/fern.config.json b/seed/pydantic-v2/alias-extends/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/alias-extends/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/alias-extends/.mock/generators.yml b/seed/pydantic-v2/alias-extends/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/alias-extends/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/alias-extends/snippet-templates.json b/seed/pydantic-v2/alias-extends/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/alias-extends/snippet.json b/seed/pydantic-v2/alias-extends/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/alias-extends/types/alias_type.py b/seed/pydantic-v2/alias-extends/types/alias_type.py new file mode 100644 index 00000000000..80c661a98ea --- /dev/null +++ b/seed/pydantic-v2/alias-extends/types/alias_type.py @@ -0,0 +1,20 @@ +from pydantic import RootModel +from .types.parent import Parent +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class AliasType(RootModel[Parent]): + root: Parent + + def get_as_parent() -> UUID: + return self.root + + @staticmethod + def from_parent(value: Parent) -> AliasType: + AliasType(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/alias-extends/types/child.py b/seed/pydantic-v2/alias-extends/types/child.py new file mode 100644 index 00000000000..23547429cce --- /dev/null +++ b/seed/pydantic-v2/alias-extends/types/child.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from .types.parent import Parent +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Child(BaseModel, Parent): + child: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/alias-extends/types/parent.py b/seed/pydantic-v2/alias-extends/types/parent.py new file mode 100644 index 00000000000..5983008ca1e --- /dev/null +++ b/seed/pydantic-v2/alias-extends/types/parent.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Parent(BaseModel): + parent: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/alias/.mock/definition/__package__.yml b/seed/pydantic-v2/alias/.mock/definition/__package__.yml new file mode 100644 index 00000000000..8737d982401 --- /dev/null +++ b/seed/pydantic-v2/alias/.mock/definition/__package__.yml @@ -0,0 +1,37 @@ +types: + TypeId: + docs: An alias for type IDs. + type: string + examples: + - name: One + value: type-kaljhv87 + + Type: + docs: A simple type with just a name. + properties: + id: TypeId + name: string + examples: + - name: One + value: + id: type-df89sdg1 + name: foo + + Object: + docs: Object is an alias for a type. + type: Type + examples: + - name: One + value: + id: kljasc85 + name: bar + +service: + auth: false + base-path: / + endpoints: + get: + path: "/{typeId}" + path-parameters: + typeId: TypeId + method: GET diff --git a/seed/pydantic-v2/alias/.mock/definition/api.yml b/seed/pydantic-v2/alias/.mock/definition/api.yml new file mode 100644 index 00000000000..6ca90528fe0 --- /dev/null +++ b/seed/pydantic-v2/alias/.mock/definition/api.yml @@ -0,0 +1 @@ +name: alias diff --git a/seed/pydantic-v2/alias/.mock/fern.config.json b/seed/pydantic-v2/alias/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/alias/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/alias/.mock/generators.yml b/seed/pydantic-v2/alias/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/alias/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/alias/snippet-templates.json b/seed/pydantic-v2/alias/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/alias/snippet.json b/seed/pydantic-v2/alias/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/alias/types/object.py b/seed/pydantic-v2/alias/types/object.py new file mode 100644 index 00000000000..5901c14aef8 --- /dev/null +++ b/seed/pydantic-v2/alias/types/object.py @@ -0,0 +1,17 @@ +from pydantic import RootModel +from .types.type import Type +from dt import datetime +from core.datetime_utils import serialize_datetime +class Object(RootModel[Type]): +"""Object is an alias for a type.""" + root: Type + def get_as_type() -> UUID: + return self.root + @staticmethod + def from_type(value: Type) -> Object: + Object(root=value) + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/alias/types/type.py b/seed/pydantic-v2/alias/types/type.py new file mode 100644 index 00000000000..86fc8dd9d6a --- /dev/null +++ b/seed/pydantic-v2/alias/types/type.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime +class Type(BaseModel): +"""A simple type with just a name.""" + id: str + name: str + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/alias/types/type_id.py b/seed/pydantic-v2/alias/types/type_id.py new file mode 100644 index 00000000000..a170fef3f7e --- /dev/null +++ b/seed/pydantic-v2/alias/types/type_id.py @@ -0,0 +1,16 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime +class TypeId(RootModel[str]): +"""An alias for type IDs.""" + root: str + def get_as_str() -> UUID: + return self.root + @staticmethod + def from_str(value: str) -> TypeId: + TypeId(root=value) + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/any-auth/.mock/definition/api.yml b/seed/pydantic-v2/any-auth/.mock/definition/api.yml new file mode 100644 index 00000000000..0915d3f623c --- /dev/null +++ b/seed/pydantic-v2/any-auth/.mock/definition/api.yml @@ -0,0 +1,31 @@ +imports: + auth: auth.yml + +name: any-auth + +auth: + any: + - Bearer + - ApiKey + - OAuth +auth-schemes: + Bearer: + scheme: bearer + token: + env: MY_TOKEN + ApiKey: + header: X-API-Key + type: string + env: MY_API_KEY + OAuth: + scheme: oauth + type: client-credentials + client-id-env: MY_CLIENT_ID + client-secret-env: MY_CLIENT_SECRET + get-token: + endpoint: auth.getToken + response-properties: + access-token: $response.access_token + expires-in: $response.expires_in + + diff --git a/seed/pydantic-v2/any-auth/.mock/definition/auth.yml b/seed/pydantic-v2/any-auth/.mock/definition/auth.yml new file mode 100644 index 00000000000..3fd00041722 --- /dev/null +++ b/seed/pydantic-v2/any-auth/.mock/definition/auth.yml @@ -0,0 +1,26 @@ +types: + TokenResponse: + docs: | + An OAuth token response. + properties: + access_token: string + expires_in: integer + refresh_token: optional + +service: + auth: false + base-path: / + endpoints: + getToken: + path: /token + method: POST + request: + name: GetTokenRequest + body: + properties: + client_id: string + client_secret: string + audience: literal<"https://api.example.com"> + grant_type: literal<"client_credentials"> + scope: optional + response: TokenResponse diff --git a/seed/pydantic-v2/any-auth/.mock/definition/user.yml b/seed/pydantic-v2/any-auth/.mock/definition/user.yml new file mode 100644 index 00000000000..c8350c2a345 --- /dev/null +++ b/seed/pydantic-v2/any-auth/.mock/definition/user.yml @@ -0,0 +1,14 @@ +types: + User: + properties: + id: string + name: string + +service: + auth: true + base-path: "" + endpoints: + get: + path: /users + method: POST + response: list diff --git a/seed/pydantic-v2/any-auth/.mock/fern.config.json b/seed/pydantic-v2/any-auth/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/any-auth/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/any-auth/.mock/generators.yml b/seed/pydantic-v2/any-auth/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/any-auth/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/any-auth/resources/auth/types/token_response.py b/seed/pydantic-v2/any-auth/resources/auth/types/token_response.py new file mode 100644 index 00000000000..2ed020441af --- /dev/null +++ b/seed/pydantic-v2/any-auth/resources/auth/types/token_response.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime +class TokenResponse(BaseModel): +"""An OAuth token response.""" + access_token: str + expires_in: int + refresh_token: Optional[str] = None + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/any-auth/resources/user/types/user.py b/seed/pydantic-v2/any-auth/resources/user/types/user.py new file mode 100644 index 00000000000..c33409914bf --- /dev/null +++ b/seed/pydantic-v2/any-auth/resources/user/types/user.py @@ -0,0 +1,11 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime +class User(BaseModel): + id: str + name: str + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/any-auth/snippet-templates.json b/seed/pydantic-v2/any-auth/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/any-auth/snippet.json b/seed/pydantic-v2/any-auth/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/api-wide-base-path/.mock/definition/api.yml b/seed/pydantic-v2/api-wide-base-path/.mock/definition/api.yml new file mode 100644 index 00000000000..be62c79078e --- /dev/null +++ b/seed/pydantic-v2/api-wide-base-path/.mock/definition/api.yml @@ -0,0 +1,4 @@ +name: api-wide-base-path +base-path: /test/{pathParam} +path-parameters: + pathParam: string diff --git a/seed/pydantic-v2/api-wide-base-path/.mock/definition/service.yml b/seed/pydantic-v2/api-wide-base-path/.mock/definition/service.yml new file mode 100644 index 00000000000..2fbaa67b3d3 --- /dev/null +++ b/seed/pydantic-v2/api-wide-base-path/.mock/definition/service.yml @@ -0,0 +1,12 @@ +service: + auth: false + base-path: "/{serviceParam}" + path-parameters: + serviceParam: string + endpoints: + post: + path: "/{endpointParam}/{resourceParam}" + path-parameters: + resourceParam: string + endpointParam: integer + method: POST diff --git a/seed/pydantic-v2/api-wide-base-path/.mock/fern.config.json b/seed/pydantic-v2/api-wide-base-path/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/api-wide-base-path/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/api-wide-base-path/.mock/generators.yml b/seed/pydantic-v2/api-wide-base-path/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/api-wide-base-path/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/api-wide-base-path/snippet-templates.json b/seed/pydantic-v2/api-wide-base-path/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/api-wide-base-path/snippet.json b/seed/pydantic-v2/api-wide-base-path/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/audiences/.mock/definition/api.yml b/seed/pydantic-v2/audiences/.mock/definition/api.yml new file mode 100644 index 00000000000..80c01321be3 --- /dev/null +++ b/seed/pydantic-v2/audiences/.mock/definition/api.yml @@ -0,0 +1,16 @@ +name: audiences +display-name: Audiences API +audiences: + - public + - private + - partner +environments: + environment-a: + url: https://api.example.a.com + audiences: + - public + environment-b: + url: https://api.example.b.com + audiences: + - private +default-environment: null \ No newline at end of file diff --git a/seed/pydantic-v2/audiences/.mock/definition/commons.yml b/seed/pydantic-v2/audiences/.mock/definition/commons.yml new file mode 100644 index 00000000000..0cdcfc9fb9b --- /dev/null +++ b/seed/pydantic-v2/audiences/.mock/definition/commons.yml @@ -0,0 +1,5 @@ +imports: + commons: commons.yml + +types: + Imported: string diff --git a/seed/pydantic-v2/audiences/.mock/definition/folder-a/service.yml b/seed/pydantic-v2/audiences/.mock/definition/folder-a/service.yml new file mode 100644 index 00000000000..11d499ee5db --- /dev/null +++ b/seed/pydantic-v2/audiences/.mock/definition/folder-a/service.yml @@ -0,0 +1,20 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + folderBCommons: ../folder-b/common.yml + +service: + auth: false + audiences: + - public + base-path: / + endpoints: + getDirectThread: + path: "" + method: GET + response: Response + +types: + Response: + properties: + foo: optional diff --git a/seed/pydantic-v2/audiences/.mock/definition/folder-b/common.yml b/seed/pydantic-v2/audiences/.mock/definition/folder-b/common.yml new file mode 100644 index 00000000000..23ab9ba28ed --- /dev/null +++ b/seed/pydantic-v2/audiences/.mock/definition/folder-b/common.yml @@ -0,0 +1,9 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + folderCCommons: ../folder-c/common.yml + +types: + Foo: + properties: + foo: optional diff --git a/seed/pydantic-v2/audiences/.mock/definition/folder-c/common.yml b/seed/pydantic-v2/audiences/.mock/definition/folder-c/common.yml new file mode 100644 index 00000000000..caae3364b2e --- /dev/null +++ b/seed/pydantic-v2/audiences/.mock/definition/folder-c/common.yml @@ -0,0 +1,6 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +types: + FolderCFoo: + properties: + bar_property: uuid diff --git a/seed/pydantic-v2/audiences/.mock/definition/folder-d/service.yml b/seed/pydantic-v2/audiences/.mock/definition/folder-d/service.yml new file mode 100644 index 00000000000..13bcaf2edf2 --- /dev/null +++ b/seed/pydantic-v2/audiences/.mock/definition/folder-d/service.yml @@ -0,0 +1,20 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + folderBCommons: ../folder-b/common.yml + +service: + auth: false + audiences: + - partner + base-path: /partner-path + endpoints: + getDirectThread: + path: "" + method: GET + response: Response + +types: + Response: + properties: + foo: string diff --git a/seed/pydantic-v2/audiences/.mock/definition/foo.yml b/seed/pydantic-v2/audiences/.mock/definition/foo.yml new file mode 100644 index 00000000000..3827e514cf6 --- /dev/null +++ b/seed/pydantic-v2/audiences/.mock/definition/foo.yml @@ -0,0 +1,46 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + commons: commons.yml + +service: + auth: false + base-path: / + endpoints: + find: + audiences: + - public + - private + path: "" + method: POST + request: + name: FindRequest + query-parameters: + optionalString: + type: OptionalString + audiences: + - private + body: + properties: + publicProperty: + type: optional + audiences: + - public + privateProperty: optional + response: ImportingType + +types: + ImportingType: + properties: + imported: commons.Imported + OptionalString: optional + + FilteredType: + audiences: + - public + properties: + public_property: + type: optional + audiences: + - public + private_property: integer diff --git a/seed/pydantic-v2/audiences/.mock/fern.config.json b/seed/pydantic-v2/audiences/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/audiences/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/audiences/.mock/generators.yml b/seed/pydantic-v2/audiences/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/audiences/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/audiences/resources/commons/types/imported.py b/seed/pydantic-v2/audiences/resources/commons/types/imported.py new file mode 100644 index 00000000000..bca598f7b52 --- /dev/null +++ b/seed/pydantic-v2/audiences/resources/commons/types/imported.py @@ -0,0 +1,19 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Imported(RootModel[str]): + root: str + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: str) -> Imported: + Imported(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/audiences/resources/folder_a/resources/service/types/response.py b/seed/pydantic-v2/audiences/resources/folder_a/resources/service/types/response.py new file mode 100644 index 00000000000..df2a7e334f8 --- /dev/null +++ b/seed/pydantic-v2/audiences/resources/folder_a/resources/service/types/response.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from resources.folder_b.resources.common.types.foo import Foo +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Response(BaseModel): + foo: Optional[Foo] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/audiences/resources/folder_b/resources/common/types/foo.py b/seed/pydantic-v2/audiences/resources/folder_b/resources/common/types/foo.py new file mode 100644 index 00000000000..f2c8bf200a1 --- /dev/null +++ b/seed/pydantic-v2/audiences/resources/folder_b/resources/common/types/foo.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from resources.folder_c.resources.common.types.folder_c_foo import FolderCFoo +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Foo(BaseModel): + foo: Optional[FolderCFoo] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/audiences/resources/folder_c/resources/common/types/folder_c_foo.py b/seed/pydantic-v2/audiences/resources/folder_c/resources/common/types/folder_c_foo.py new file mode 100644 index 00000000000..6de8ab57d01 --- /dev/null +++ b/seed/pydantic-v2/audiences/resources/folder_c/resources/common/types/folder_c_foo.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from uuid import UUID +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class FolderCFoo(BaseModel): + bar_property: UUID + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/audiences/resources/folder_d/resources/service/types/response.py b/seed/pydantic-v2/audiences/resources/folder_d/resources/service/types/response.py new file mode 100644 index 00000000000..865c2b9a59b --- /dev/null +++ b/seed/pydantic-v2/audiences/resources/folder_d/resources/service/types/response.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Response(BaseModel): + foo: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/audiences/resources/foo/types/filtered_type.py b/seed/pydantic-v2/audiences/resources/foo/types/filtered_type.py new file mode 100644 index 00000000000..334a96841d3 --- /dev/null +++ b/seed/pydantic-v2/audiences/resources/foo/types/filtered_type.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class FilteredType(BaseModel): + public_property: Optional[str] = None + private_property: int + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/audiences/resources/foo/types/importing_type.py b/seed/pydantic-v2/audiences/resources/foo/types/importing_type.py new file mode 100644 index 00000000000..f777bbecfaa --- /dev/null +++ b/seed/pydantic-v2/audiences/resources/foo/types/importing_type.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ImportingType(BaseModel): + imported: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/audiences/resources/foo/types/optional_string.py b/seed/pydantic-v2/audiences/resources/foo/types/optional_string.py new file mode 100644 index 00000000000..7eef91b3a41 --- /dev/null +++ b/seed/pydantic-v2/audiences/resources/foo/types/optional_string.py @@ -0,0 +1,20 @@ +from pydantic import RootModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class OptionalString(RootModel[Optional[str]]): + root: Optional[str] + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: Optional[str]) -> OptionalString: + OptionalString(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/audiences/snippet-templates.json b/seed/pydantic-v2/audiences/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/audiences/snippet.json b/seed/pydantic-v2/audiences/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/auth-environment-variables/.mock/definition/api.yml b/seed/pydantic-v2/auth-environment-variables/.mock/definition/api.yml new file mode 100644 index 00000000000..f253d1d1590 --- /dev/null +++ b/seed/pydantic-v2/auth-environment-variables/.mock/definition/api.yml @@ -0,0 +1,14 @@ +name: auth-environment-variables +auth: APIKey +auth-schemes: + APIKey: + header: X-FERN-API-KEY + type: string + env: FERN_API_KEY +headers: + X-Another-Header: + type: string + env: ANOTHER_ENV_VAR + X-API-Version: + type: literal<"01-01-2000"> + env: VERSION diff --git a/seed/pydantic-v2/auth-environment-variables/.mock/definition/service.yml b/seed/pydantic-v2/auth-environment-variables/.mock/definition/service.yml new file mode 100644 index 00000000000..9e5d595f4a2 --- /dev/null +++ b/seed/pydantic-v2/auth-environment-variables/.mock/definition/service.yml @@ -0,0 +1,25 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +service: + auth: false + base-path: "" + endpoints: + getWithApiKey: + auth: true + docs: GET request with custom api key + path: /apiKey + method: GET + response: string + + getWithHeader: + docs: GET request with custom api key + path: /apiKeyInHeader + method: GET + request: + name: HeaderAuthRequest + headers: + X-Endpoint-Header: + docs: "Specifies the endpoint key." + type: string + env: MY_HEADER_ENV + response: string diff --git a/seed/pydantic-v2/auth-environment-variables/.mock/fern.config.json b/seed/pydantic-v2/auth-environment-variables/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/auth-environment-variables/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/auth-environment-variables/.mock/generators.yml b/seed/pydantic-v2/auth-environment-variables/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/auth-environment-variables/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/auth-environment-variables/snippet-templates.json b/seed/pydantic-v2/auth-environment-variables/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/auth-environment-variables/snippet.json b/seed/pydantic-v2/auth-environment-variables/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/basic-auth-environment-variables/.mock/definition/api.yml b/seed/pydantic-v2/basic-auth-environment-variables/.mock/definition/api.yml new file mode 100644 index 00000000000..828c6eced71 --- /dev/null +++ b/seed/pydantic-v2/basic-auth-environment-variables/.mock/definition/api.yml @@ -0,0 +1,13 @@ +name: basic-auth-environment-variables +auth: Basic +auth-schemes: + Basic: + scheme: basic + username: + name: username + env: USERNAME + password: + name: password + env: PASSWORD +error-discrimination: + strategy: status-code diff --git a/seed/pydantic-v2/basic-auth-environment-variables/.mock/definition/basic-auth.yml b/seed/pydantic-v2/basic-auth-environment-variables/.mock/definition/basic-auth.yml new file mode 100644 index 00000000000..8a04bc9f070 --- /dev/null +++ b/seed/pydantic-v2/basic-auth-environment-variables/.mock/definition/basic-auth.yml @@ -0,0 +1,35 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + errors: ./errors.yml + +service: + auth: false + base-path: "" + endpoints: + getWithBasicAuth: + auth: true + docs: GET request with basic auth scheme + path: /basic-auth + method: GET + response: + boolean + # headers: + # WWW-Authenticate: optional # Specifies which auth scheme to use if CustomAuthScheme was not applied + # body: + # success: boolean + errors: + - errors.UnauthorizedRequest + + postWithBasicAuth: + auth: true + docs: POST request with basic auth scheme + path: /basic-auth + method: POST + request: + name: PostWithBasicAuth + body: unknown + response: boolean + errors: + - errors.UnauthorizedRequest + - errors.BadRequest diff --git a/seed/pydantic-v2/basic-auth-environment-variables/.mock/definition/errors.yml b/seed/pydantic-v2/basic-auth-environment-variables/.mock/definition/errors.yml new file mode 100644 index 00000000000..cdd6a966703 --- /dev/null +++ b/seed/pydantic-v2/basic-auth-environment-variables/.mock/definition/errors.yml @@ -0,0 +1,11 @@ +errors: + UnauthorizedRequest: + status-code: 401 + type: UnauthorizedRequestErrorBody + BadRequest: + status-code: 400 + +types: + UnauthorizedRequestErrorBody: + properties: + message: string diff --git a/seed/pydantic-v2/basic-auth-environment-variables/.mock/fern.config.json b/seed/pydantic-v2/basic-auth-environment-variables/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/basic-auth-environment-variables/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/basic-auth-environment-variables/.mock/generators.yml b/seed/pydantic-v2/basic-auth-environment-variables/.mock/generators.yml new file mode 100644 index 00000000000..9e26dfeeb6e --- /dev/null +++ b/seed/pydantic-v2/basic-auth-environment-variables/.mock/generators.yml @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/seed/pydantic-v2/basic-auth-environment-variables/resources/errors/types/unauthorized_request_error_body.py b/seed/pydantic-v2/basic-auth-environment-variables/resources/errors/types/unauthorized_request_error_body.py new file mode 100644 index 00000000000..b1ed2dd64d1 --- /dev/null +++ b/seed/pydantic-v2/basic-auth-environment-variables/resources/errors/types/unauthorized_request_error_body.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UnauthorizedRequestErrorBody(BaseModel): + message: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/basic-auth-environment-variables/snippet-templates.json b/seed/pydantic-v2/basic-auth-environment-variables/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/basic-auth-environment-variables/snippet.json b/seed/pydantic-v2/basic-auth-environment-variables/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/basic-auth/.mock/definition/api.yml b/seed/pydantic-v2/basic-auth/.mock/definition/api.yml new file mode 100644 index 00000000000..2d6df22f2d1 --- /dev/null +++ b/seed/pydantic-v2/basic-auth/.mock/definition/api.yml @@ -0,0 +1,4 @@ +name: basic-auth +auth: basic +error-discrimination: + strategy: status-code diff --git a/seed/pydantic-v2/basic-auth/.mock/definition/basic-auth.yml b/seed/pydantic-v2/basic-auth/.mock/definition/basic-auth.yml new file mode 100644 index 00000000000..8a04bc9f070 --- /dev/null +++ b/seed/pydantic-v2/basic-auth/.mock/definition/basic-auth.yml @@ -0,0 +1,35 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + errors: ./errors.yml + +service: + auth: false + base-path: "" + endpoints: + getWithBasicAuth: + auth: true + docs: GET request with basic auth scheme + path: /basic-auth + method: GET + response: + boolean + # headers: + # WWW-Authenticate: optional # Specifies which auth scheme to use if CustomAuthScheme was not applied + # body: + # success: boolean + errors: + - errors.UnauthorizedRequest + + postWithBasicAuth: + auth: true + docs: POST request with basic auth scheme + path: /basic-auth + method: POST + request: + name: PostWithBasicAuth + body: unknown + response: boolean + errors: + - errors.UnauthorizedRequest + - errors.BadRequest diff --git a/seed/pydantic-v2/basic-auth/.mock/definition/errors.yml b/seed/pydantic-v2/basic-auth/.mock/definition/errors.yml new file mode 100644 index 00000000000..cdd6a966703 --- /dev/null +++ b/seed/pydantic-v2/basic-auth/.mock/definition/errors.yml @@ -0,0 +1,11 @@ +errors: + UnauthorizedRequest: + status-code: 401 + type: UnauthorizedRequestErrorBody + BadRequest: + status-code: 400 + +types: + UnauthorizedRequestErrorBody: + properties: + message: string diff --git a/seed/pydantic-v2/basic-auth/.mock/fern.config.json b/seed/pydantic-v2/basic-auth/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/basic-auth/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/basic-auth/.mock/generators.yml b/seed/pydantic-v2/basic-auth/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/basic-auth/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/basic-auth/resources/errors/types/unauthorized_request_error_body.py b/seed/pydantic-v2/basic-auth/resources/errors/types/unauthorized_request_error_body.py new file mode 100644 index 00000000000..b1ed2dd64d1 --- /dev/null +++ b/seed/pydantic-v2/basic-auth/resources/errors/types/unauthorized_request_error_body.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UnauthorizedRequestErrorBody(BaseModel): + message: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/basic-auth/snippet-templates.json b/seed/pydantic-v2/basic-auth/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/basic-auth/snippet.json b/seed/pydantic-v2/basic-auth/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/bearer-token-environment-variable/.mock/definition/api.yml b/seed/pydantic-v2/bearer-token-environment-variable/.mock/definition/api.yml new file mode 100644 index 00000000000..819d8807966 --- /dev/null +++ b/seed/pydantic-v2/bearer-token-environment-variable/.mock/definition/api.yml @@ -0,0 +1,8 @@ +name: bearer-token-environment-variable +auth: Bearer +auth-schemes: + Bearer: + scheme: bearer + token: + name: apiKey + env: COURIER_API_KEY diff --git a/seed/pydantic-v2/bearer-token-environment-variable/.mock/definition/service.yml b/seed/pydantic-v2/bearer-token-environment-variable/.mock/definition/service.yml new file mode 100644 index 00000000000..d38a6ca2913 --- /dev/null +++ b/seed/pydantic-v2/bearer-token-environment-variable/.mock/definition/service.yml @@ -0,0 +1,12 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +service: + auth: false + base-path: "" + endpoints: + getWithBearerToken: + auth: true + docs: GET request with custom api key + path: /apiKey + method: GET + response: string diff --git a/seed/pydantic-v2/bearer-token-environment-variable/.mock/fern.config.json b/seed/pydantic-v2/bearer-token-environment-variable/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/bearer-token-environment-variable/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/bearer-token-environment-variable/.mock/generators.yml b/seed/pydantic-v2/bearer-token-environment-variable/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/bearer-token-environment-variable/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/bearer-token-environment-variable/snippet-templates.json b/seed/pydantic-v2/bearer-token-environment-variable/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/bearer-token-environment-variable/snippet.json b/seed/pydantic-v2/bearer-token-environment-variable/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/bytes/.mock/definition/api.yml b/seed/pydantic-v2/bytes/.mock/definition/api.yml new file mode 100644 index 00000000000..cdfcf5be4a1 --- /dev/null +++ b/seed/pydantic-v2/bytes/.mock/definition/api.yml @@ -0,0 +1 @@ +name: bytes diff --git a/seed/pydantic-v2/bytes/.mock/definition/service.yml b/seed/pydantic-v2/bytes/.mock/definition/service.yml new file mode 100644 index 00000000000..b0610fa616c --- /dev/null +++ b/seed/pydantic-v2/bytes/.mock/definition/service.yml @@ -0,0 +1,10 @@ +service: + auth: false + base-path: "" + endpoints: + upload: + path: /upload-content + method: POST + request: + content-type: "application/octet-stream" + body: bytes diff --git a/seed/pydantic-v2/bytes/.mock/fern.config.json b/seed/pydantic-v2/bytes/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/bytes/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/bytes/.mock/generators.yml b/seed/pydantic-v2/bytes/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/bytes/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/bytes/snippet-templates.json b/seed/pydantic-v2/bytes/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/bytes/snippet.json b/seed/pydantic-v2/bytes/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/circular-references-advanced/.mock/definition/__package__.yml b/seed/pydantic-v2/circular-references-advanced/.mock/definition/__package__.yml new file mode 100644 index 00000000000..35979beb883 --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/.mock/definition/__package__.yml @@ -0,0 +1,13 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + a: a.yml + +types: + ImportingA: + properties: + a: optional + + RootType: + properties: + s: string diff --git a/seed/pydantic-v2/circular-references-advanced/.mock/definition/a.yml b/seed/pydantic-v2/circular-references-advanced/.mock/definition/a.yml new file mode 100644 index 00000000000..50553c25d2b --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/.mock/definition/a.yml @@ -0,0 +1,8 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + root: __package__.yml + +types: + A: + extends: root.RootType diff --git a/seed/pydantic-v2/circular-references-advanced/.mock/definition/api.yml b/seed/pydantic-v2/circular-references-advanced/.mock/definition/api.yml new file mode 100644 index 00000000000..9a8ae7d166b --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/.mock/definition/api.yml @@ -0,0 +1 @@ +name: api diff --git a/seed/pydantic-v2/circular-references-advanced/.mock/definition/ast.yml b/seed/pydantic-v2/circular-references-advanced/.mock/definition/ast.yml new file mode 100644 index 00000000000..c48c39070df --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/.mock/definition/ast.yml @@ -0,0 +1,23 @@ +types: + ContainerValue: + union: + list: list + optional: optional + PrimitiveValue: + enum: + - STRING + - NUMBER + ObjectValue: + properties: {} + FieldName: string + FieldValue: + union: + primitive_value: PrimitiveValue + object_value: ObjectValue + container_value: ContainerValue + ObjectFieldValue: + docs: This type allows us to test a circular reference with a union type (see FieldValue). + properties: + name: FieldName + value: FieldValue + diff --git a/seed/pydantic-v2/circular-references-advanced/.mock/fern.config.json b/seed/pydantic-v2/circular-references-advanced/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/circular-references-advanced/.mock/generators.yml b/seed/pydantic-v2/circular-references-advanced/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/circular-references-advanced/resources/a/types/a.py b/seed/pydantic-v2/circular-references-advanced/resources/a/types/a.py new file mode 100644 index 00000000000..139fa30867e --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/resources/a/types/a.py @@ -0,0 +1,10 @@ +from pydantic import BaseModel +from types.root_type import RootType +from dt import datetime +from core.datetime_utils import serialize_datetime +class A(BaseModel, RootType): + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/circular-references-advanced/resources/ast/types/field_name.py b/seed/pydantic-v2/circular-references-advanced/resources/ast/types/field_name.py new file mode 100644 index 00000000000..4c3c7bf38c1 --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/resources/ast/types/field_name.py @@ -0,0 +1,15 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime +class FieldName(RootModel[str]): + root: str + def get_as_str() -> UUID: + return self.root + @staticmethod + def from_str(value: str) -> FieldName: + FieldName(root=value) + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/circular-references-advanced/resources/ast/types/object_field_value.py b/seed/pydantic-v2/circular-references-advanced/resources/ast/types/object_field_value.py new file mode 100644 index 00000000000..09a448fd03d --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/resources/ast/types/object_field_value.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from resources.ast.types.field_value import FieldValue +from dt import datetime +from core.datetime_utils import serialize_datetime +class ObjectFieldValue(BaseModel): +"""This type allows us to test a circular reference with a union type (see FieldValue).""" + name: str + value: FieldValue + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/circular-references-advanced/resources/ast/types/object_value.py b/seed/pydantic-v2/circular-references-advanced/resources/ast/types/object_value.py new file mode 100644 index 00000000000..58c0e5c70b6 --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/resources/ast/types/object_value.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime +class ObjectValue(BaseModel): + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/circular-references-advanced/snippet-templates.json b/seed/pydantic-v2/circular-references-advanced/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/circular-references-advanced/snippet.json b/seed/pydantic-v2/circular-references-advanced/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/circular-references-advanced/types/importing_a.py b/seed/pydantic-v2/circular-references-advanced/types/importing_a.py new file mode 100644 index 00000000000..f0c8d75fc54 --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/types/importing_a.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from typing import Optional +from resources.a.types.a import A +from dt import datetime +from core.datetime_utils import serialize_datetime +class ImportingA(BaseModel): + a: Optional[A] = None + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/circular-references-advanced/types/root_type.py b/seed/pydantic-v2/circular-references-advanced/types/root_type.py new file mode 100644 index 00000000000..14b81f4acc3 --- /dev/null +++ b/seed/pydantic-v2/circular-references-advanced/types/root_type.py @@ -0,0 +1,10 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime +class RootType(BaseModel): + s: str + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/circular-references/.mock/definition/__package__.yml b/seed/pydantic-v2/circular-references/.mock/definition/__package__.yml new file mode 100644 index 00000000000..35979beb883 --- /dev/null +++ b/seed/pydantic-v2/circular-references/.mock/definition/__package__.yml @@ -0,0 +1,13 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + a: a.yml + +types: + ImportingA: + properties: + a: optional + + RootType: + properties: + s: string diff --git a/seed/pydantic-v2/circular-references/.mock/definition/a.yml b/seed/pydantic-v2/circular-references/.mock/definition/a.yml new file mode 100644 index 00000000000..50553c25d2b --- /dev/null +++ b/seed/pydantic-v2/circular-references/.mock/definition/a.yml @@ -0,0 +1,8 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + root: __package__.yml + +types: + A: + extends: root.RootType diff --git a/seed/pydantic-v2/circular-references/.mock/definition/api.yml b/seed/pydantic-v2/circular-references/.mock/definition/api.yml new file mode 100644 index 00000000000..9a8ae7d166b --- /dev/null +++ b/seed/pydantic-v2/circular-references/.mock/definition/api.yml @@ -0,0 +1 @@ +name: api diff --git a/seed/pydantic-v2/circular-references/.mock/definition/ast.yml b/seed/pydantic-v2/circular-references/.mock/definition/ast.yml new file mode 100644 index 00000000000..4d9e43d0c96 --- /dev/null +++ b/seed/pydantic-v2/circular-references/.mock/definition/ast.yml @@ -0,0 +1,24 @@ +types: + FieldValue: + union: + primitive_value: PrimitiveValue + object_value: ObjectValue + container_value: ContainerValue + ContainerValue: + union: + list: list + optional: optional + PrimitiveValue: + enum: + - STRING + - NUMBER + ObjectValue: + properties: {} + JsonLike: + discriminated: false + union: + - list + - map + - string + - integer + - boolean diff --git a/seed/pydantic-v2/circular-references/.mock/fern.config.json b/seed/pydantic-v2/circular-references/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/circular-references/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/circular-references/.mock/generators.yml b/seed/pydantic-v2/circular-references/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/circular-references/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/circular-references/resources/a/types/a.py b/seed/pydantic-v2/circular-references/resources/a/types/a.py new file mode 100644 index 00000000000..d2b7ba42b2c --- /dev/null +++ b/seed/pydantic-v2/circular-references/resources/a/types/a.py @@ -0,0 +1,11 @@ +from pydantic import BaseModel +from types.root_type import RootType +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class A(BaseModel, RootType): + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/circular-references/resources/ast/types/object_value.py b/seed/pydantic-v2/circular-references/resources/ast/types/object_value.py new file mode 100644 index 00000000000..3aaba108efa --- /dev/null +++ b/seed/pydantic-v2/circular-references/resources/ast/types/object_value.py @@ -0,0 +1,10 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ObjectValue(BaseModel): + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/circular-references/snippet-templates.json b/seed/pydantic-v2/circular-references/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/circular-references/snippet.json b/seed/pydantic-v2/circular-references/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/circular-references/types/importing_a.py b/seed/pydantic-v2/circular-references/types/importing_a.py new file mode 100644 index 00000000000..b244dfbe62b --- /dev/null +++ b/seed/pydantic-v2/circular-references/types/importing_a.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from resources.a.types.a import A +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ImportingA(BaseModel): + a: Optional[A] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/circular-references/types/root_type.py b/seed/pydantic-v2/circular-references/types/root_type.py new file mode 100644 index 00000000000..38f81334f22 --- /dev/null +++ b/seed/pydantic-v2/circular-references/types/root_type.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class RootType(BaseModel): + s: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/cross-package-type-names/.mock/definition/api.yml b/seed/pydantic-v2/cross-package-type-names/.mock/definition/api.yml new file mode 100644 index 00000000000..f5655049c1b --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/.mock/definition/api.yml @@ -0,0 +1,2 @@ +name: cross-package-type-names +default-environment: null \ No newline at end of file diff --git a/seed/pydantic-v2/cross-package-type-names/.mock/definition/commons.yml b/seed/pydantic-v2/cross-package-type-names/.mock/definition/commons.yml new file mode 100644 index 00000000000..0cdcfc9fb9b --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/.mock/definition/commons.yml @@ -0,0 +1,5 @@ +imports: + commons: commons.yml + +types: + Imported: string diff --git a/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-a/service.yml b/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-a/service.yml new file mode 100644 index 00000000000..f1689cb232d --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-a/service.yml @@ -0,0 +1,18 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + folderBCommons: ../folder-b/common.yml + +service: + auth: false + base-path: / + endpoints: + getDirectThread: + path: "" + method: GET + response: Response + +types: + Response: + properties: + foo: optional diff --git a/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-b/common.yml b/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-b/common.yml new file mode 100644 index 00000000000..fe77c996c07 --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-b/common.yml @@ -0,0 +1,9 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + folderCCommons: ../folder-c/common.yml + +types: + Foo: + properties: + foo: optional diff --git a/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-c/common.yml b/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-c/common.yml new file mode 100644 index 00000000000..5911f31e57f --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-c/common.yml @@ -0,0 +1,6 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +types: + Foo: + properties: + bar_property: uuid diff --git a/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-d/service.yml b/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-d/service.yml new file mode 100644 index 00000000000..f1689cb232d --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/.mock/definition/folder-d/service.yml @@ -0,0 +1,18 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + folderBCommons: ../folder-b/common.yml + +service: + auth: false + base-path: / + endpoints: + getDirectThread: + path: "" + method: GET + response: Response + +types: + Response: + properties: + foo: optional diff --git a/seed/pydantic-v2/cross-package-type-names/.mock/definition/foo.yml b/seed/pydantic-v2/cross-package-type-names/.mock/definition/foo.yml new file mode 100644 index 00000000000..c2f42ee8407 --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/.mock/definition/foo.yml @@ -0,0 +1,29 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + commons: commons.yml + +service: + auth: false + base-path: / + endpoints: + find: + path: "" + method: POST + request: + name: FindRequest + query-parameters: + optionalString: + type: OptionalString + body: + properties: + publicProperty: + type: optional + privateProperty: optional + response: ImportingType + +types: + ImportingType: + properties: + imported: commons.Imported + OptionalString: optional diff --git a/seed/pydantic-v2/cross-package-type-names/.mock/fern.config.json b/seed/pydantic-v2/cross-package-type-names/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/cross-package-type-names/.mock/generators.yml b/seed/pydantic-v2/cross-package-type-names/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/cross-package-type-names/resources/commons/types/imported.py b/seed/pydantic-v2/cross-package-type-names/resources/commons/types/imported.py new file mode 100644 index 00000000000..bca598f7b52 --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/resources/commons/types/imported.py @@ -0,0 +1,19 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Imported(RootModel[str]): + root: str + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: str) -> Imported: + Imported(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/cross-package-type-names/resources/folder_a/resources/service/types/response.py b/seed/pydantic-v2/cross-package-type-names/resources/folder_a/resources/service/types/response.py new file mode 100644 index 00000000000..df2a7e334f8 --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/resources/folder_a/resources/service/types/response.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from resources.folder_b.resources.common.types.foo import Foo +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Response(BaseModel): + foo: Optional[Foo] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/cross-package-type-names/resources/folder_b/resources/common/types/foo.py b/seed/pydantic-v2/cross-package-type-names/resources/folder_b/resources/common/types/foo.py new file mode 100644 index 00000000000..07885b311be --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/resources/folder_b/resources/common/types/foo.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from resources.folder_c.resources.common.types.foo import Foo +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Foo(BaseModel): + foo: Optional[Foo] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/cross-package-type-names/resources/folder_c/resources/common/types/foo.py b/seed/pydantic-v2/cross-package-type-names/resources/folder_c/resources/common/types/foo.py new file mode 100644 index 00000000000..d05f2f615a6 --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/resources/folder_c/resources/common/types/foo.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from uuid import UUID +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Foo(BaseModel): + bar_property: UUID + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/cross-package-type-names/resources/folder_d/resources/service/types/response.py b/seed/pydantic-v2/cross-package-type-names/resources/folder_d/resources/service/types/response.py new file mode 100644 index 00000000000..df2a7e334f8 --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/resources/folder_d/resources/service/types/response.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from resources.folder_b.resources.common.types.foo import Foo +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Response(BaseModel): + foo: Optional[Foo] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/cross-package-type-names/resources/foo/types/importing_type.py b/seed/pydantic-v2/cross-package-type-names/resources/foo/types/importing_type.py new file mode 100644 index 00000000000..f777bbecfaa --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/resources/foo/types/importing_type.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ImportingType(BaseModel): + imported: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/cross-package-type-names/resources/foo/types/optional_string.py b/seed/pydantic-v2/cross-package-type-names/resources/foo/types/optional_string.py new file mode 100644 index 00000000000..7eef91b3a41 --- /dev/null +++ b/seed/pydantic-v2/cross-package-type-names/resources/foo/types/optional_string.py @@ -0,0 +1,20 @@ +from pydantic import RootModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class OptionalString(RootModel[Optional[str]]): + root: Optional[str] + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: Optional[str]) -> OptionalString: + OptionalString(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/cross-package-type-names/snippet-templates.json b/seed/pydantic-v2/cross-package-type-names/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/cross-package-type-names/snippet.json b/seed/pydantic-v2/cross-package-type-names/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/custom-auth/.mock/definition/api.yml b/seed/pydantic-v2/custom-auth/.mock/definition/api.yml new file mode 100644 index 00000000000..1d61eeff283 --- /dev/null +++ b/seed/pydantic-v2/custom-auth/.mock/definition/api.yml @@ -0,0 +1,8 @@ +name: custom-auth +auth: CustomAuthScheme +auth-schemes: + CustomAuthScheme: + header: X-API-KEY + type: string +error-discrimination: + strategy: status-code diff --git a/seed/pydantic-v2/custom-auth/.mock/definition/custom-auth.yml b/seed/pydantic-v2/custom-auth/.mock/definition/custom-auth.yml new file mode 100644 index 00000000000..de23674da02 --- /dev/null +++ b/seed/pydantic-v2/custom-auth/.mock/definition/custom-auth.yml @@ -0,0 +1,30 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + errors: ./errors.yml + +service: + auth: false + base-path: "" + endpoints: + getWithCustomAuth: + auth: true + docs: GET request with custom auth scheme + path: /custom-auth + method: GET + response: boolean + errors: + - errors.UnauthorizedRequest + + postWithCustomAuth: + auth: true + docs: POST request with custom auth scheme + path: /custom-auth + method: POST + request: + name: PostWithCustomAuth + body: unknown + response: boolean + errors: + - errors.UnauthorizedRequest + - errors.BadRequest diff --git a/seed/pydantic-v2/custom-auth/.mock/definition/errors.yml b/seed/pydantic-v2/custom-auth/.mock/definition/errors.yml new file mode 100644 index 00000000000..cdd6a966703 --- /dev/null +++ b/seed/pydantic-v2/custom-auth/.mock/definition/errors.yml @@ -0,0 +1,11 @@ +errors: + UnauthorizedRequest: + status-code: 401 + type: UnauthorizedRequestErrorBody + BadRequest: + status-code: 400 + +types: + UnauthorizedRequestErrorBody: + properties: + message: string diff --git a/seed/pydantic-v2/custom-auth/.mock/fern.config.json b/seed/pydantic-v2/custom-auth/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/custom-auth/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/custom-auth/.mock/generators.yml b/seed/pydantic-v2/custom-auth/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/custom-auth/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/custom-auth/resources/errors/types/unauthorized_request_error_body.py b/seed/pydantic-v2/custom-auth/resources/errors/types/unauthorized_request_error_body.py new file mode 100644 index 00000000000..b1ed2dd64d1 --- /dev/null +++ b/seed/pydantic-v2/custom-auth/resources/errors/types/unauthorized_request_error_body.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UnauthorizedRequestErrorBody(BaseModel): + message: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/custom-auth/snippet-templates.json b/seed/pydantic-v2/custom-auth/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/custom-auth/snippet.json b/seed/pydantic-v2/custom-auth/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/enum/.mock/definition/__package__.yml b/seed/pydantic-v2/enum/.mock/definition/__package__.yml new file mode 100644 index 00000000000..a72e076f94d --- /dev/null +++ b/seed/pydantic-v2/enum/.mock/definition/__package__.yml @@ -0,0 +1,38 @@ +types: + Operand: + docs: | + Tests enum name and value can be + different. + enum: + - value: ">" + name: GREATER_THAN + - value: "=" + name: EQUAL_TO + - value: "less_than" + docs: | + The name and value should be similar + are similar for less than. + examples: + - name: GreaterThan + value: ">" + - name: LessThan + value: "less_than" + + Color: + enum: + - value: "red" + name: RED + - value: "blue" + name: BLUE + examples: + - name: Red + value: "red" + + ColorOrOperand: + discriminated: false + union: + - Color + - Operand + examples: + - name: Red + value: "red" diff --git a/seed/pydantic-v2/enum/.mock/definition/api.yml b/seed/pydantic-v2/enum/.mock/definition/api.yml new file mode 100644 index 00000000000..3e2ce7d17a8 --- /dev/null +++ b/seed/pydantic-v2/enum/.mock/definition/api.yml @@ -0,0 +1 @@ +name: enum diff --git a/seed/pydantic-v2/enum/.mock/definition/inlined-request.yml b/seed/pydantic-v2/enum/.mock/definition/inlined-request.yml new file mode 100644 index 00000000000..f17deabdaaf --- /dev/null +++ b/seed/pydantic-v2/enum/.mock/definition/inlined-request.yml @@ -0,0 +1,24 @@ +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + send: + path: /inlined + method: POST + request: + name: SendEnumInlinedRequest + body: + properties: + operand: + type: root.Operand + maybeOperand: optional + operandOrColor: root.ColorOrOperand + maybeOperandOrColor: optional + examples: + - request: + operand: $root.Operand.GreaterThan + operandOrColor: $root.ColorOrOperand.Red + \ No newline at end of file diff --git a/seed/pydantic-v2/enum/.mock/definition/path-param.yml b/seed/pydantic-v2/enum/.mock/definition/path-param.yml new file mode 100644 index 00000000000..5afc7329f1e --- /dev/null +++ b/seed/pydantic-v2/enum/.mock/definition/path-param.yml @@ -0,0 +1,17 @@ +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + send: + path: /path/{operand}/{operandOrColor} + method: POST + path-parameters: + operand: root.Operand + operandOrColor: root.ColorOrOperand + examples: + - path-parameters: + operand: $root.Operand.GreaterThan + operandOrColor: $root.ColorOrOperand.Red diff --git a/seed/pydantic-v2/enum/.mock/definition/query-param.yml b/seed/pydantic-v2/enum/.mock/definition/query-param.yml new file mode 100644 index 00000000000..2b3724eba7e --- /dev/null +++ b/seed/pydantic-v2/enum/.mock/definition/query-param.yml @@ -0,0 +1,40 @@ +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + send: + path: /query + method: POST + request: + name: SendEnumAsQueryParamRequest + query-parameters: + operand: root.Operand + maybeOperand: optional + operandOrColor: root.ColorOrOperand + maybeOperandOrColor: optional + examples: + - query-parameters: + operand: $root.Operand.GreaterThan + operandOrColor: $root.ColorOrOperand.Red + + sendList: + path: /query-list + method: POST + request: + name: SendEnumListAsQueryParamRequest + query-parameters: + operand: + type: root.Operand + allow-multiple: true + maybeOperand: + type: optional + allow-multiple: true + operandOrColor: + type: root.ColorOrOperand + allow-multiple: true + maybeOperandOrColor: + type: optional + allow-multiple: true diff --git a/seed/pydantic-v2/enum/.mock/fern.config.json b/seed/pydantic-v2/enum/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/enum/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/enum/.mock/generators.yml b/seed/pydantic-v2/enum/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/enum/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/enum/snippet-templates.json b/seed/pydantic-v2/enum/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/enum/snippet.json b/seed/pydantic-v2/enum/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/error-property/.mock/definition/api.yml b/seed/pydantic-v2/error-property/.mock/definition/api.yml new file mode 100644 index 00000000000..48a882c38b3 --- /dev/null +++ b/seed/pydantic-v2/error-property/.mock/definition/api.yml @@ -0,0 +1,4 @@ +name: error-property +error-discrimination: + strategy: property + property-name: errorName diff --git a/seed/pydantic-v2/error-property/.mock/definition/errors.yml b/seed/pydantic-v2/error-property/.mock/definition/errors.yml new file mode 100644 index 00000000000..b700adf4582 --- /dev/null +++ b/seed/pydantic-v2/error-property/.mock/definition/errors.yml @@ -0,0 +1,9 @@ +errors: + PropertyBasedErrorTest: #returns a JSON object with { ErrorName: PropertyBasedErrorTest, body: {PropertyBasedErrorTestBody}} + status-code: 400 + type: PropertyBasedErrorTestBody + +types: + PropertyBasedErrorTestBody: + properties: + message: string diff --git a/seed/pydantic-v2/error-property/.mock/definition/property-based-error.yml b/seed/pydantic-v2/error-property/.mock/definition/property-based-error.yml new file mode 100644 index 00000000000..dd93ae75fc0 --- /dev/null +++ b/seed/pydantic-v2/error-property/.mock/definition/property-based-error.yml @@ -0,0 +1,18 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +#return an error no matter what for this endpoint so that the errorName can be confirmed + +imports: + errors: ./errors.yml + +service: + auth: false + base-path: "" + endpoints: + ThrowError: + docs: GET request that always throws an error + path: /property-based-error + method: GET + response: string + errors: + - errors.PropertyBasedErrorTest diff --git a/seed/pydantic-v2/error-property/.mock/fern.config.json b/seed/pydantic-v2/error-property/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/error-property/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/error-property/.mock/generators.yml b/seed/pydantic-v2/error-property/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/error-property/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/error-property/resources/errors/types/property_based_error_test_body.py b/seed/pydantic-v2/error-property/resources/errors/types/property_based_error_test_body.py new file mode 100644 index 00000000000..f90afd34389 --- /dev/null +++ b/seed/pydantic-v2/error-property/resources/errors/types/property_based_error_test_body.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class PropertyBasedErrorTestBody(BaseModel): + message: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/error-property/snippet-templates.json b/seed/pydantic-v2/error-property/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/error-property/snippet.json b/seed/pydantic-v2/error-property/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/examples/.mock/definition/__package__.yml b/seed/pydantic-v2/examples/.mock/definition/__package__.yml new file mode 100644 index 00000000000..6ffd6f61506 --- /dev/null +++ b/seed/pydantic-v2/examples/.mock/definition/__package__.yml @@ -0,0 +1,48 @@ +types: + Type: + discriminated: false + union: + - BasicType + - ComplexType + + Identifier: + properties: + type: Type + value: string + label: string + + BasicType: + enum: + - name: Primitive + value: primitive + - name: Literal + value: literal + + ComplexType: + enum: + - name: Object + value: object + - name: Union + value: union + - name: unknown + value: unknown + +service: + auth: false + base-path: / + endpoints: + echo: + method: POST + path: "" + request: string + response: string + examples: + - request: Hello world!\n\nwith\n\tnewlines + response: + body: Hello world!\n\nwith\n\tnewlines + + createType: + method: POST + path: "" + request: Type + response: Identifier \ No newline at end of file diff --git a/seed/pydantic-v2/examples/.mock/definition/api.yml b/seed/pydantic-v2/examples/.mock/definition/api.yml new file mode 100644 index 00000000000..3f3cb4540de --- /dev/null +++ b/seed/pydantic-v2/examples/.mock/definition/api.yml @@ -0,0 +1,8 @@ +name: examples +auth: bearer +error-discrimination: + strategy: status-code +environments: + Production: https://production.com/api + Staging: https://staging.com/api +default-environment: null diff --git a/seed/pydantic-v2/examples/.mock/definition/commons/types.yml b/seed/pydantic-v2/examples/.mock/definition/commons/types.yml new file mode 100644 index 00000000000..33f95a4ab1b --- /dev/null +++ b/seed/pydantic-v2/examples/.mock/definition/commons/types.yml @@ -0,0 +1,43 @@ +types: + Tag: + type: string + examples: + - name: One + value: tag-wf9as23d + + Metadata: + properties: + id: string + data: optional> + jsonString: optional + examples: + - name: One + value: + id: metadata-js8dg24b + data: + foo: bar + baz: qux + jsonString: '{"foo": "bar", "baz": "qux"}' + + EventInfo: + union: + metadata: Metadata + tag: Tag + examples: + - name: Metadata + value: + type: metadata + id: metadata-alskjfg8 + data: + one: two + jsonString: '{"one": "two"}' + + Data: + union: + string: string + base64: base64 + examples: + - name: String + value: + type: string + value: data diff --git a/seed/pydantic-v2/examples/.mock/definition/file/notification/service.yml b/seed/pydantic-v2/examples/.mock/definition/file/notification/service.yml new file mode 100644 index 00000000000..7f518565dcf --- /dev/null +++ b/seed/pydantic-v2/examples/.mock/definition/file/notification/service.yml @@ -0,0 +1,18 @@ +imports: + types: ../../types.yml + +service: + auth: true + base-path: /file/notification/{notificationId} + path-parameters: + notificationId: string + endpoints: + getException: + method: GET + path: "" + response: types.Exception + examples: + - path-parameters: + notificationId: notification-hsy129x + response: + body: $types.Exception.One diff --git a/seed/pydantic-v2/examples/.mock/definition/file/service.yml b/seed/pydantic-v2/examples/.mock/definition/file/service.yml new file mode 100644 index 00000000000..349d80d6543 --- /dev/null +++ b/seed/pydantic-v2/examples/.mock/definition/file/service.yml @@ -0,0 +1,37 @@ +imports: + types: ../types.yml + +types: + Filename: + type: string + examples: + - name: Example0 + value: file.txt + +service: + auth: true + base-path: /file + headers: + X-File-API-Version: string + endpoints: + getFile: + docs: "This endpoint returns a file by its name." + method: GET + path: /{filename} + path-parameters: + filename: + type: string + docs: This is a filename + request: + name: GetFileRequest + response: types.File + errors: + - types.NotFoundError + examples: + - path-parameters: + filename: $Filename.Example0 + headers: + X-File-API-Version: 0.0.2 + response: + error: types.NotFoundError + body: A file with that name was not found! diff --git a/seed/pydantic-v2/examples/.mock/definition/health/service.yml b/seed/pydantic-v2/examples/.mock/definition/health/service.yml new file mode 100644 index 00000000000..46ba829d120 --- /dev/null +++ b/seed/pydantic-v2/examples/.mock/definition/health/service.yml @@ -0,0 +1,32 @@ +imports: + types: ../types.yml + +service: + auth: true + base-path: / + endpoints: + check: + docs: "This endpoint checks the health of a resource." + method: GET + path: /check/{id} + path-parameters: + id: + type: string + docs: The id to check + examples: + - name: Example0 + path-parameters: + id: id-2sdx82h + - name: Example2 + path-parameters: + id: id-3tey93i + + ping: + docs: "This endpoint checks the health of the service." + method: GET + path: /ping + response: boolean + examples: + - name: Example0 + response: + body: true diff --git a/seed/pydantic-v2/examples/.mock/definition/service.yml b/seed/pydantic-v2/examples/.mock/definition/service.yml new file mode 100644 index 00000000000..f564c7ce7e2 --- /dev/null +++ b/seed/pydantic-v2/examples/.mock/definition/service.yml @@ -0,0 +1,56 @@ +imports: + types: types.yml + +service: + auth: false + base-path: / + endpoints: + getMovie: + method: GET + path: /movie/{movieId} + path-parameters: + movieId: types.MovieId + response: types.Movie + examples: + - path-parameters: + movieId: $types.MovieId.One + response: + body: $types.Movie.One + + createMovie: + method: POST + path: /movie + request: types.Movie + response: types.MovieId + examples: + - request: $types.Movie.One + response: + body: $types.MovieId.One + + getMetadata: + method: GET + path: /metadata + request: + name: GetMetadataRequest + query-parameters: + shallow: optional + tag: + type: optional + allow-multiple: true + headers: + X-API-Version: string + response: types.Metadata + examples: + - query-parameters: + shallow: false + tag: development + headers: + X-API-Version: 0.0.1 + response: + body: $types.Metadata.One + + createBigEntity: + method: POST + path: /big-entity + request: types.BigEntity + response: types.Response \ No newline at end of file diff --git a/seed/pydantic-v2/examples/.mock/definition/types.yml b/seed/pydantic-v2/examples/.mock/definition/types.yml new file mode 100644 index 00000000000..ecceebe129c --- /dev/null +++ b/seed/pydantic-v2/examples/.mock/definition/types.yml @@ -0,0 +1,314 @@ +imports: + commons: commons/types.yml + root: __package__.yml + +errors: + NotFoundError: + status-code: 404 + type: string + +types: + MovieId: + type: string + examples: + - name: One + value: movie-c06a4ad7 + + Movie: + properties: + id: MovieId + prequel: optional + title: string + from: string + rating: + type: double + docs: The rating scale is one to five stars + type: literal<"movie"> + tag: commons.Tag + book: optional + metadata: map + revenue: long + examples: + - name: One + value: + id: $MovieId.One + prequel: "movie-cv9b914f" + title: The Boy and the Heron + from: Hayao Miyazaki + rating: 8.0 + type: movie + tag: $commons.Tag.One + metadata: + actors: + - Christian Bale + - Florence Pugh + - Willem Dafoe + releaseDate: "2023-12-08" + ratings: + rottenTomatoes: 97 + imdb: 7.6 + revenue: 1000000 + + CastMember: + discriminated: false + union: + - Actor + - Actress + - StuntDouble + examples: + - name: Example0 + value: + id: actor_123 + name: "Brad Pitt" + - name: Example1 + value: $Actress.Example0 + + Actor: + properties: + name: string + id: string + + Actress: + properties: + name: string + id: string + examples: + - name: Example0 + value: + name: Jennifer Lawrence + id: actor_456 + + StuntDouble: + properties: + name: string + actorOrActressId: string + + ExtendedMovie: + extends: Movie + properties: + cast: list + examples: + - value: + id: movie-sda231x + title: Pulp Fiction + from: Quentin Tarantino + rating: 8.5 + type: movie + tag: tag-12efs9dv + cast: + - John Travolta + - Samuel L. Jackson + - Uma Thurman + - Bruce Willis + metadata: + academyAward: true + releaseDate: "2023-12-08" + ratings: + rottenTomatoes: 97 + imdb: 7.6 + revenue: 1000000 + + Moment: + properties: + id: uuid + date: date + datetime: datetime + examples: + - value: + id: 656f12d6-f592-444c-a1d3-a3cfd46d5b39 + date: 1994-01-01 + datetime: 1994-01-01T01:01:01Z + + File: + properties: + name: string + contents: string + examples: + - name: One + value: + name: file.txt + contents: ... + - name: Two + value: + name: another_file.txt + contents: ... + + Directory: + properties: + name: string + files: optional> + directories: optional> + examples: + - name: One + value: + name: root + files: + - $File.One + directories: + - name: tmp + files: + - $File.Two + + Node: + properties: + name: string + nodes: optional> + trees: optional> + examples: + - name: Tree + value: + name: root + nodes: + - $Node.Left + - $Node.Right + trees: + - $Tree.Root + - name: Left + value: + name: left + - name: Right + value: + name: right + + Tree: + properties: + nodes: optional> + examples: + - name: Root + value: + nodes: + - $Node.Left + - $Node.Right + + Metadata: + base-properties: + extra: map + tags: set + union: + html: string + markdown: string + examples: + - name: One + value: + type: html + extra: + version: 0.0.1 + tenancy: test + tags: + - development + - public + value: ... + + Exception: + union: + generic: ExceptionInfo + timeout: {} + examples: + - name: One + value: + type: generic + exceptionType: Unavailable + exceptionMessage: This component is unavailable! + exceptionStacktrace: + + ExceptionInfo: + properties: + exceptionType: string + exceptionMessage: string + exceptionStacktrace: string + examples: + - name: One + value: + exceptionType: Unavailable + exceptionMessage: This component is unavailable! + exceptionStacktrace: + + MigrationStatus: + enum: + - value: RUNNING + docs: The migration is running. + - value: FAILED + docs: The migration failed. + - FINISHED + examples: + - name: Running + value: RUNNING + - name: Failed + value: FAILED + + Migration: + properties: + name: string + status: MigrationStatus + examples: + - value: + name: 001_init + status: $MigrationStatus.Running + + Request: + properties: + request: unknown + examples: + - name: Empty + value: + request: {} + + Response: + properties: + response: unknown + identifiers: list + examples: + - name: String + value: + response: "Initializing..." + identifiers: + - type: primitive + value: 'example' + label: Primitive + - type: unknown + value: '{}' + label: Unknown + + ResponseType: + properties: + type: root.Type + + Test: + union: + and: boolean + or: boolean + examples: + - name: And + value: + type: and + value: true + - name: Or + value: + type: or + value: true + + Entity: + properties: + type: root.Type + name: string + examples: + - name: One + value: + type: unknown + name: unknown + + BigEntity: + properties: + castMember: optional + extendedMovie: optional + entity: optional + metadata: optional + commonMetadata: optional + eventInfo: optional + data: optional + migration: optional + exception: optional + test: optional + node: optional + directory: optional + moment: optional diff --git a/seed/pydantic-v2/examples/.mock/fern.config.json b/seed/pydantic-v2/examples/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/examples/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/examples/.mock/generators.yml b/seed/pydantic-v2/examples/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/examples/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/examples/resources/commons/resources/types/types/metadata.py b/seed/pydantic-v2/examples/resources/commons/resources/types/types/metadata.py new file mode 100644 index 00000000000..6bd190834a7 --- /dev/null +++ b/seed/pydantic-v2/examples/resources/commons/resources/types/types/metadata.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel +from typing import Optional, Dict +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Metadata(BaseModel): + id: str + data: Optional[Dict[str, str]] = None + json_string: Optional[str] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/commons/resources/types/types/tag.py b/seed/pydantic-v2/examples/resources/commons/resources/types/types/tag.py new file mode 100644 index 00000000000..9be1c20d23d --- /dev/null +++ b/seed/pydantic-v2/examples/resources/commons/resources/types/types/tag.py @@ -0,0 +1,19 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Tag(RootModel[str]): + root: str + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: str) -> Tag: + Tag(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/file/resources/service/types/filename.py b/seed/pydantic-v2/examples/resources/file/resources/service/types/filename.py new file mode 100644 index 00000000000..642ca36def9 --- /dev/null +++ b/seed/pydantic-v2/examples/resources/file/resources/service/types/filename.py @@ -0,0 +1,19 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Filename(RootModel[str]): + root: str + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: str) -> Filename: + Filename(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/actor.py b/seed/pydantic-v2/examples/resources/types/types/actor.py new file mode 100644 index 00000000000..2a0ca861fb7 --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/actor.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Actor(BaseModel): + name: str + id: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/actress.py b/seed/pydantic-v2/examples/resources/types/types/actress.py new file mode 100644 index 00000000000..e74c70e8cbb --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/actress.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Actress(BaseModel): + name: str + id: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/big_entity.py b/seed/pydantic-v2/examples/resources/types/types/big_entity.py new file mode 100644 index 00000000000..589edf4c1be --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/big_entity.py @@ -0,0 +1,38 @@ +from pydantic import BaseModel +from typing import Optional +from resources.types.types.cast_member import CastMember +from resources.types.types.extended_movie import ExtendedMovie +from resources.types.types.entity import Entity +from resources.types.types.metadata import Metadata +from resources.commons.resources.types.types.metadata import Metadata +from resources.commons.resources.types.types.event_info import EventInfo +from resources.commons.resources.types.types.data import Data +from resources.types.types.migration import Migration +from resources.types.types.exception import Exception +from resources.types.types.test import Test +from resources.types.types.node import Node +from resources.types.types.directory import Directory +from resources.types.types.moment import Moment +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class BigEntity(BaseModel): + cast_member: Optional[CastMember] + extended_movie: Optional[ExtendedMovie] + entity: Optional[Entity] = None + metadata: Optional[Metadata] = None + common_metadata: Optional[Metadata] + event_info: Optional[EventInfo] + data: Optional[Data] = None + migration: Optional[Migration] = None + exception: Optional[Exception] = None + test: Optional[Test] = None + node: Optional[Node] = None + directory: Optional[Directory] = None + moment: Optional[Moment] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/directory.py b/seed/pydantic-v2/examples/resources/types/types/directory.py new file mode 100644 index 00000000000..f6ce4623d4a --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/directory.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel +from typing import Optional, List +from resources.types.types.file import File +from resources.types.types.directory import Directory +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Directory(BaseModel): + name: str + files: Optional[List[File]] = None + directories: Optional[List[Directory]] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/entity.py b/seed/pydantic-v2/examples/resources/types/types/entity.py new file mode 100644 index 00000000000..2be7924b22c --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/entity.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from types.type import Type +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Entity(BaseModel): + type: Type + name: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/exception_info.py b/seed/pydantic-v2/examples/resources/types/types/exception_info.py new file mode 100644 index 00000000000..c29011aa0f1 --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/exception_info.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ExceptionInfo(BaseModel): + exception_type: str + exception_message: str + exception_stacktrace: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/extended_movie.py b/seed/pydantic-v2/examples/resources/types/types/extended_movie.py new file mode 100644 index 00000000000..dda63a5bd5d --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/extended_movie.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from resources.types.types.movie import Movie +from typing import List +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ExtendedMovie(BaseModel, Movie): + cast: List[str] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/file.py b/seed/pydantic-v2/examples/resources/types/types/file.py new file mode 100644 index 00000000000..ae36883611b --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/file.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class File(BaseModel): + name: str + contents: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/migration.py b/seed/pydantic-v2/examples/resources/types/types/migration.py new file mode 100644 index 00000000000..33e718afa61 --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/migration.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from resources.types.types.migration_status import MigrationStatus +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Migration(BaseModel): + name: str + status: MigrationStatus + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/moment.py b/seed/pydantic-v2/examples/resources/types/types/moment.py new file mode 100644 index 00000000000..6b186825d59 --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/moment.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel +from uuid import UUID +from datetime import datetime +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Moment(BaseModel): + id: UUID + date: str + datetime: datetime + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/movie.py b/seed/pydantic-v2/examples/resources/types/types/movie.py new file mode 100644 index 00000000000..03d68e992aa --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/movie.py @@ -0,0 +1,25 @@ +from pydantic import BaseModel +from typing import Optional, Dict, Any +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Movie(BaseModel): + id: str + prequel: Optional[str] = None + title: str + from_: str + rating: float + """ + The rating scale is one to five stars + """ + type: str + tag: str + book: Optional[str] = None + metadata: Dict[str, Any] + revenue: int + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/movie_id.py b/seed/pydantic-v2/examples/resources/types/types/movie_id.py new file mode 100644 index 00000000000..d18d5e6749e --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/movie_id.py @@ -0,0 +1,19 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class MovieId(RootModel[str]): + root: str + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: str) -> MovieId: + MovieId(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/node.py b/seed/pydantic-v2/examples/resources/types/types/node.py new file mode 100644 index 00000000000..ec9b7a01a1c --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/node.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel +from typing import Optional, List +from resources.types.types.node import Node +from resources.types.types.tree import Tree +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Node(BaseModel): + name: str + nodes: Optional[List[Node]] = None + trees: Optional[List[Tree]] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/request.py b/seed/pydantic-v2/examples/resources/types/types/request.py new file mode 100644 index 00000000000..d257522f16e --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/request.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import Any +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Request(BaseModel): + request: Any + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/response.py b/seed/pydantic-v2/examples/resources/types/types/response.py new file mode 100644 index 00000000000..a43a54bd9ef --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/response.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel +from typing import Any, List +from types.identifier import Identifier +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Response(BaseModel): + response: Any + identifiers: List[Identifier] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/response_type.py b/seed/pydantic-v2/examples/resources/types/types/response_type.py new file mode 100644 index 00000000000..45a148d4339 --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/response_type.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from types.type import Type +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ResponseType(BaseModel): + type: Type + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/stunt_double.py b/seed/pydantic-v2/examples/resources/types/types/stunt_double.py new file mode 100644 index 00000000000..72ba3a84c9a --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/stunt_double.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class StuntDouble(BaseModel): + name: str + actor_or_actress_id: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/resources/types/types/tree.py b/seed/pydantic-v2/examples/resources/types/types/tree.py new file mode 100644 index 00000000000..eb25ec483cc --- /dev/null +++ b/seed/pydantic-v2/examples/resources/types/types/tree.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional, List +from resources.types.types.node import Node +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Tree(BaseModel): + nodes: Optional[List[Node]] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/examples/snippet-templates.json b/seed/pydantic-v2/examples/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/examples/snippet.json b/seed/pydantic-v2/examples/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/examples/types/identifier.py b/seed/pydantic-v2/examples/types/identifier.py new file mode 100644 index 00000000000..670642a42ed --- /dev/null +++ b/seed/pydantic-v2/examples/types/identifier.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel +from .types.type import Type +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Identifier(BaseModel): + type: Type + value: str + label: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/api.yml b/seed/pydantic-v2/exhaustive/.mock/definition/api.yml new file mode 100644 index 00000000000..dd65915538f --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/api.yml @@ -0,0 +1,4 @@ +name: exhaustive +auth: bearer +error-discrimination: + strategy: status-code diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/container.yml b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/container.yml new file mode 100644 index 00000000000..165a039dc65 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/container.yml @@ -0,0 +1,48 @@ +imports: + objects: ../types/object.yml + +service: + auth: true + base-path: /container + endpoints: + getAndReturnListOfPrimitives: + path: /list-of-primitives + method: POST + request: list + response: list + + getAndReturnListOfObjects: + path: /list-of-objects + method: POST + request: list + response: list + + getAndReturnSetOfPrimitives: + path: /set-of-primitives + method: POST + request: set + response: set + + getAndReturnSetOfObjects: + path: /set-of-objects + method: POST + request: set + response: set + + getAndReturnMapPrimToPrim: + path: /map-prim-to-prim + method: POST + request: map + response: map + + getAndReturnMapOfPrimToObject: + path: /map-prim-to-object + method: POST + request: map + response: map + + getAndReturnOptional: + path: /opt-objects + method: POST + request: optional + response: optional diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/enum.yml b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/enum.yml new file mode 100644 index 00000000000..335a0889cc7 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/enum.yml @@ -0,0 +1,12 @@ +imports: + enums: ../types/enum.yml + +service: + auth: true + base-path: /enum + endpoints: + getAndReturnEnum: + method: POST + path: "" + request: enums.WeatherReport + response: enums.WeatherReport diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/http-methods.yml b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/http-methods.yml new file mode 100644 index 00000000000..51a54c0802c --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/http-methods.yml @@ -0,0 +1,43 @@ +imports: + objects: ../types/object.yml + +service: + auth: true + base-path: /http-methods + + endpoints: + testGet: + method: GET + path: /{id} + path-parameters: + id: string + response: string + + testPost: + method: POST + path: "" + request: objects.ObjectWithRequiredField + response: objects.ObjectWithOptionalField + + testPut: + method: PUT + path: /{id} + path-parameters: + id: string + request: objects.ObjectWithRequiredField + response: objects.ObjectWithOptionalField + + testPatch: + method: PATCH + path: /{id} + path-parameters: + id: string + request: objects.ObjectWithOptionalField + response: objects.ObjectWithOptionalField + + testDelete: + method: DELETE + path: /{id} + path-parameters: + id: string + response: boolean diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/object.yml b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/object.yml new file mode 100644 index 00000000000..9fad6aa2776 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/object.yml @@ -0,0 +1,44 @@ +imports: + objects: ../types/object.yml + +service: + auth: true + base-path: /object + endpoints: + getAndReturnWithOptionalField: + path: /get-and-return-with-optional-field + method: POST + request: objects.ObjectWithOptionalField + response: objects.ObjectWithOptionalField + + getAndReturnWithRequiredField: + path: /get-and-return-with-required-field + method: POST + request: objects.ObjectWithRequiredField + response: objects.ObjectWithRequiredField + + getAndReturnWithMapOfMap: + path: /get-and-return-with-map-of-map + method: POST + request: objects.ObjectWithMapOfMap + response: objects.ObjectWithMapOfMap + + getAndReturnNestedWithOptionalField: + path: /get-and-return-nested-with-optional-field + method: POST + request: objects.NestedObjectWithOptionalField + response: objects.NestedObjectWithOptionalField + + getAndReturnNestedWithRequiredField: + path: /get-and-return-nested-with-required-field/{string} + method: POST + path-parameters: + string: string + request: objects.NestedObjectWithRequiredField + response: objects.NestedObjectWithRequiredField + + getAndReturnNestedWithRequiredFieldAsList: + path: /get-and-return-nested-with-required-field-list + method: POST + request: list + response: objects.NestedObjectWithRequiredField diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/params.yml b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/params.yml new file mode 100644 index 00000000000..7766547ad79 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/params.yml @@ -0,0 +1,57 @@ +service: + auth: true + base-path: /params + endpoints: + getWithPath: + docs: GET with path param + path: /path/{param} + path-parameters: + param: string + method: GET + response: string + + getWithQuery: + docs: GET with query param + path: "" + method: GET + request: + name: GetWithQuery + query-parameters: + query: string #mandatory for test + number: integer + + getWithAllowMultipleQuery: + docs: GET with multiple of same query param + path: "" + method: GET + request: + name: GetWithMultipleQuery + query-parameters: + query: + type: string + allow-multiple: true + numer: + type: integer + allow-multiple: true + + getWithPathAndQuery: + docs: GET with path and query params + path: /path-query/{param} + path-parameters: + param: string + method: GET + request: + name: GetWithPathAndQuery + query-parameters: + query: string #mandatory for test + + modifyWithPath: + docs: PUT to update with path param + path: /path/{param} + path-parameters: + param: string + method: PUT + request: + name: ModifyResourceAtPath + body: string + response: string diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/primitive.yml b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/primitive.yml new file mode 100644 index 00000000000..8dd7674164c --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/primitive.yml @@ -0,0 +1,60 @@ +imports: + objects: ../types/object.yml + +service: + auth: true + base-path: /primitive + endpoints: + getAndReturnString: + path: /string + method: POST + request: string + response: string + + getAndReturnInt: + path: /integer + method: POST + request: integer + response: integer + + getAndReturnLong: + path: /long + method: POST + request: long + response: long + + getAndReturnDouble: + path: /double + method: POST + request: double + response: double + + getAndReturnBool: + path: /boolean + method: POST + request: boolean + response: boolean + + getAndReturnDatetime: + path: /datetime + method: POST + request: datetime + response: datetime + + getAndReturnDate: + path: /date + method: POST + request: date + response: date + + getAndReturnUUID: + path: /uuid + method: POST + request: uuid + response: uuid + + getAndReturnBase64: + path: /base64 + method: POST + request: base64 + response: base64 diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/union.yml b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/union.yml new file mode 100644 index 00000000000..ce9021160d7 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/endpoints/union.yml @@ -0,0 +1,12 @@ +imports: + unions: ../types/union.yml + +service: + auth: true + base-path: /union + endpoints: + getAndReturnUnion: + method: POST + path: "" + request: unions.Animal + response: unions.Animal diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/general-errors.yml b/seed/pydantic-v2/exhaustive/.mock/definition/general-errors.yml new file mode 100644 index 00000000000..5fbf9cfc417 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/general-errors.yml @@ -0,0 +1,9 @@ +errors: + BadRequestBody: + status-code: 400 + type: BadObjectRequestInfo + +types: + BadObjectRequestInfo: + properties: + message: string diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/inlined-requests.yml b/seed/pydantic-v2/exhaustive/.mock/definition/inlined-requests.yml new file mode 100644 index 00000000000..9347fe7e335 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/inlined-requests.yml @@ -0,0 +1,25 @@ +imports: + objects: ./types/object.yml + errors: ./general-errors.yml + +# test req bodies, path params, query params, multiple query params, etc. +# test union and enum as well + +service: + auth: false + base-path: /req-bodies + endpoints: + postWithObjectBodyandResponse: + docs: POST with custom object in request body, response is an object + path: /object + method: POST + request: + name: PostWithObjectBody + body: + properties: + string: string + integer: integer + NestedObject: objects.ObjectWithOptionalField + response: objects.ObjectWithOptionalField + errors: + - errors.BadRequestBody diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/no-auth.yml b/seed/pydantic-v2/exhaustive/.mock/definition/no-auth.yml new file mode 100644 index 00000000000..e3c33ed7fab --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/no-auth.yml @@ -0,0 +1,20 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + general-errors: ./general-errors.yml + +service: + auth: false + base-path: /no-auth + endpoints: + postWithNoAuth: + auth: false + docs: POST request with no auth + path: "" + method: POST + request: + name: PostWithNoAuth + body: unknown + response: boolean + errors: + - general-errors.BadRequestBody diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/no-req-body.yml b/seed/pydantic-v2/exhaustive/.mock/definition/no-req-body.yml new file mode 100644 index 00000000000..daffd9a495c --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/no-req-body.yml @@ -0,0 +1,16 @@ +imports: + objects: ./types/object.yml + +service: + auth: true + base-path: /no-req-body + endpoints: + getWithNoRequestBody: + path: "" + method: GET + response: objects.ObjectWithOptionalField + + postWithNoRequestBody: + path: "" + method: POST + response: string diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/req-with-headers.yml b/seed/pydantic-v2/exhaustive/.mock/definition/req-with-headers.yml new file mode 100644 index 00000000000..9e49725782f --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/req-with-headers.yml @@ -0,0 +1,14 @@ +service: + base-path: /test-headers + auth: true + headers: + X-TEST-SERVICE-HEADER: string + endpoints: + getWithCustomHeader: + path: /custom-header + method: POST + request: + name: ReqWithHeaders + headers: + X-TEST-ENDPOINT-HEADER: string + body: string diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/types/enum.yml b/seed/pydantic-v2/exhaustive/.mock/definition/types/enum.yml new file mode 100644 index 00000000000..a90686092e9 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/types/enum.yml @@ -0,0 +1,12 @@ +types: + WeatherReport: + enum: + - SUNNY + - CLOUDY + - RAINING + - SNOWING + +errors: + ErrorWithEnumBody: + status-code: 400 + type: WeatherReport #does this even make sense? the type of the error body would be enum, and it could only be one of the 4 values? diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/types/object.yml b/seed/pydantic-v2/exhaustive/.mock/definition/types/object.yml new file mode 100644 index 00000000000..a165ed94cfe --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/types/object.yml @@ -0,0 +1,59 @@ +types: + ObjectWithOptionalField: #generic object that supports any type, makes it easier to use when testing + properties: + string: + type: optional + docs: This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + integer: optional + long: optional + double: optional + bool: optional + datetime: optional + date: optional + uuid: optional + base64: optional + list: optional> + set: optional> + map: optional> + bigint: optional + + ObjectWithRequiredField: + properties: + string: string + + ObjectWithMapOfMap: + properties: + map: map> + + NestedObjectWithOptionalField: + properties: + string: optional + NestedObject: optional + + NestedObjectWithRequiredField: + properties: + string: string + NestedObject: ObjectWithOptionalField + + DoubleOptional: + properties: + optionalAlias: optional + + OptionalAlias: optional + +errors: + ObjectWithOptionalFieldError: + status-code: 400 + type: ObjectWithOptionalField + + ObjectWithRequiredFieldError: + status-code: 400 + type: ObjectWithRequiredField + + NestedObjectWithOptionalFieldError: + status-code: 400 + type: NestedObjectWithOptionalField + + NestedObjectWithRequiredFieldError: + status-code: 400 + type: NestedObjectWithRequiredField diff --git a/seed/pydantic-v2/exhaustive/.mock/definition/types/union.yml b/seed/pydantic-v2/exhaustive/.mock/definition/types/union.yml new file mode 100644 index 00000000000..99ce8c75ed0 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/definition/types/union.yml @@ -0,0 +1,21 @@ +types: + Animal: + discriminant: animal + union: + dog: Dog + cat: Cat + + Dog: + properties: + name: string + likesToWoof: boolean + + Cat: + properties: + name: string + likesToMeow: boolean + +errors: + ErrorWithUnionBody: + status-code: 400 + type: Animal #has to send either dog or cat object in error body diff --git a/seed/pydantic-v2/exhaustive/.mock/fern.config.json b/seed/pydantic-v2/exhaustive/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/exhaustive/.mock/generators.yml b/seed/pydantic-v2/exhaustive/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/exhaustive/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/exhaustive/resources/general_errors/types/bad_object_request_info.py b/seed/pydantic-v2/exhaustive/resources/general_errors/types/bad_object_request_info.py new file mode 100644 index 00000000000..291b3584199 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/resources/general_errors/types/bad_object_request_info.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class BadObjectRequestInfo(BaseModel): + message: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/double_optional.py b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/double_optional.py new file mode 100644 index 00000000000..2845167b3c9 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/double_optional.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class DoubleOptional(BaseModel): + optional_alias: Optional[Optional[str]] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/nested_object_with_optional_field.py b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/nested_object_with_optional_field.py new file mode 100644 index 00000000000..671aaca7bf2 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/nested_object_with_optional_field.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel +from typing import Optional +from resources.types.resources.object.types.object_with_optional_field import ( + ObjectWithOptionalField, +) +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class NestedObjectWithOptionalField(BaseModel): + string: Optional[str] = None + nested_object: Optional[ObjectWithOptionalField] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/nested_object_with_required_field.py b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/nested_object_with_required_field.py new file mode 100644 index 00000000000..24cdbc73cc0 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/nested_object_with_required_field.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel +from resources.types.resources.object.types.object_with_optional_field import ( + ObjectWithOptionalField, +) +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class NestedObjectWithRequiredField(BaseModel): + string: str + nested_object: ObjectWithOptionalField + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/object_with_map_of_map.py b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/object_with_map_of_map.py new file mode 100644 index 00000000000..48509979230 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/object_with_map_of_map.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import Dict +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ObjectWithMapOfMap(BaseModel): + map_: Dict[str, Dict[str, str]] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/object_with_optional_field.py b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/object_with_optional_field.py new file mode 100644 index 00000000000..e62353d62f4 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/object_with_optional_field.py @@ -0,0 +1,30 @@ +from pydantic import BaseModel +from typing import Optional, List, Set, Dict +from datetime import datetime +from uuid import UUID +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ObjectWithOptionalField(BaseModel): + string: Optional[str] = None + """ + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + """ + integer: Optional[int] = None + long_: Optional[int] + double: Optional[float] = None + bool_: Optional[bool] + datetime: Optional[datetime] = None + date: Optional[str] = None + uuid_: Optional[UUID] + base_64: Optional[bytes] + list_: Optional[List[str]] + set_: Optional[Set[str]] + map_: Optional[Dict[int, str]] + bigint: Optional[str] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/object_with_required_field.py b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/object_with_required_field.py new file mode 100644 index 00000000000..6e575132a6c --- /dev/null +++ b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/object_with_required_field.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ObjectWithRequiredField(BaseModel): + string: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/optional_alias.py b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/optional_alias.py new file mode 100644 index 00000000000..04019f986cb --- /dev/null +++ b/seed/pydantic-v2/exhaustive/resources/types/resources/object/types/optional_alias.py @@ -0,0 +1,20 @@ +from pydantic import RootModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class OptionalAlias(RootModel[Optional[str]]): + root: Optional[str] + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: Optional[str]) -> OptionalAlias: + OptionalAlias(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/exhaustive/resources/types/resources/union/types/cat.py b/seed/pydantic-v2/exhaustive/resources/types/resources/union/types/cat.py new file mode 100644 index 00000000000..b997e985dc7 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/resources/types/resources/union/types/cat.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Cat(BaseModel): + name: str + likes_to_meow: bool + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/exhaustive/resources/types/resources/union/types/dog.py b/seed/pydantic-v2/exhaustive/resources/types/resources/union/types/dog.py new file mode 100644 index 00000000000..0111cd78b84 --- /dev/null +++ b/seed/pydantic-v2/exhaustive/resources/types/resources/union/types/dog.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Dog(BaseModel): + name: str + likes_to_woof: bool + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/exhaustive/snippet-templates.json b/seed/pydantic-v2/exhaustive/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/exhaustive/snippet.json b/seed/pydantic-v2/exhaustive/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/extends/.mock/definition/__package__.yml b/seed/pydantic-v2/extends/.mock/definition/__package__.yml new file mode 100644 index 00000000000..110080301d7 --- /dev/null +++ b/seed/pydantic-v2/extends/.mock/definition/__package__.yml @@ -0,0 +1,52 @@ +service: + auth: false + base-path: /extends + endpoints: + extendedInlineRequestBody: + path: /extended-inline-request-body + method: POST + request: + name: Inlined + body: + properties: + unique: string + extends: ExampleType +types: + ExampleType: + extends: Docs + properties: + name: string + examples: + - name: One + value: + docs: This is an example type. + name: Example + + NestedType: + extends: JSON + properties: + name: string + examples: + - name: One + value: + docs: This is an example nested type. + name: NestedExample + raw: '{"nested": "example"}' + + Docs: + properties: + docs: string + examples: + - name: One + value: + docs: Types extend this type to include a docs property. + + JSON: + extends: Docs + properties: + raw: string + examples: + - name: One + value: + docs: Types extend this type to include a docs and json property. + raw: '{"docs": true, "json": true}' diff --git a/seed/pydantic-v2/extends/.mock/definition/api.yml b/seed/pydantic-v2/extends/.mock/definition/api.yml new file mode 100644 index 00000000000..3d8c3b68e2d --- /dev/null +++ b/seed/pydantic-v2/extends/.mock/definition/api.yml @@ -0,0 +1 @@ +name: extends diff --git a/seed/pydantic-v2/extends/.mock/fern.config.json b/seed/pydantic-v2/extends/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/extends/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/extends/.mock/generators.yml b/seed/pydantic-v2/extends/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/extends/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/extends/snippet-templates.json b/seed/pydantic-v2/extends/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/extends/snippet.json b/seed/pydantic-v2/extends/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/extends/types/docs.py b/seed/pydantic-v2/extends/types/docs.py new file mode 100644 index 00000000000..bc94b5f60c3 --- /dev/null +++ b/seed/pydantic-v2/extends/types/docs.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Docs(BaseModel): + docs: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/extends/types/example_type.py b/seed/pydantic-v2/extends/types/example_type.py new file mode 100644 index 00000000000..780ebff5a37 --- /dev/null +++ b/seed/pydantic-v2/extends/types/example_type.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from .types.docs import Docs +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ExampleType(BaseModel, Docs): + name: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/extends/types/json.py b/seed/pydantic-v2/extends/types/json.py new file mode 100644 index 00000000000..26c4ccc10e4 --- /dev/null +++ b/seed/pydantic-v2/extends/types/json.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from .types.docs import Docs +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Json(BaseModel, Docs): + raw: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/extends/types/nested_type.py b/seed/pydantic-v2/extends/types/nested_type.py new file mode 100644 index 00000000000..d4709ecf1f4 --- /dev/null +++ b/seed/pydantic-v2/extends/types/nested_type.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from .types.json import Json +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class NestedType(BaseModel, Json): + name: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/extra-properties/.mock/definition/__package__.yml b/seed/pydantic-v2/extra-properties/.mock/definition/__package__.yml new file mode 100644 index 00000000000..24bbfd0a4e5 --- /dev/null +++ b/seed/pydantic-v2/extra-properties/.mock/definition/__package__.yml @@ -0,0 +1,5 @@ +types: + Failure: + extra-properties: true + properties: + status: literal<"failure"> diff --git a/seed/pydantic-v2/extra-properties/.mock/definition/api.yml b/seed/pydantic-v2/extra-properties/.mock/definition/api.yml new file mode 100644 index 00000000000..63aac580b28 --- /dev/null +++ b/seed/pydantic-v2/extra-properties/.mock/definition/api.yml @@ -0,0 +1 @@ +name: extra-properties \ No newline at end of file diff --git a/seed/pydantic-v2/extra-properties/.mock/definition/user.yml b/seed/pydantic-v2/extra-properties/.mock/definition/user.yml new file mode 100644 index 00000000000..bd4e43eaa67 --- /dev/null +++ b/seed/pydantic-v2/extra-properties/.mock/definition/user.yml @@ -0,0 +1,22 @@ +types: + User: + extra-properties: true + properties: + name: string + +service: + auth: false + base-path: / + endpoints: + createUser: + path: /user + method: POST + request: + name: CreateUserRequest + body: + extra-properties: true + properties: + _type: literal<"CreateUserRequest"> + _version: literal<"v1"> + name: string + response: User \ No newline at end of file diff --git a/seed/pydantic-v2/extra-properties/.mock/fern.config.json b/seed/pydantic-v2/extra-properties/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/extra-properties/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/extra-properties/.mock/generators.yml b/seed/pydantic-v2/extra-properties/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/extra-properties/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/extra-properties/resources/user/types/user.py b/seed/pydantic-v2/extra-properties/resources/user/types/user.py new file mode 100644 index 00000000000..7f16724e3d4 --- /dev/null +++ b/seed/pydantic-v2/extra-properties/resources/user/types/user.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class User(BaseModel): + name: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/extra-properties/snippet-templates.json b/seed/pydantic-v2/extra-properties/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/extra-properties/snippet.json b/seed/pydantic-v2/extra-properties/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/extra-properties/types/failure.py b/seed/pydantic-v2/extra-properties/types/failure.py new file mode 100644 index 00000000000..860a7960653 --- /dev/null +++ b/seed/pydantic-v2/extra-properties/types/failure.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Failure(BaseModel): + status: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/file-download/.mock/definition/api.yml b/seed/pydantic-v2/file-download/.mock/definition/api.yml new file mode 100644 index 00000000000..567ec30f014 --- /dev/null +++ b/seed/pydantic-v2/file-download/.mock/definition/api.yml @@ -0,0 +1 @@ +name: file-download diff --git a/seed/pydantic-v2/file-download/.mock/definition/service.yml b/seed/pydantic-v2/file-download/.mock/definition/service.yml new file mode 100644 index 00000000000..0742fce9edb --- /dev/null +++ b/seed/pydantic-v2/file-download/.mock/definition/service.yml @@ -0,0 +1,8 @@ +service: + auth: false + base-path: / + endpoints: + downloadFile: + path: "" + method: POST + response: file diff --git a/seed/pydantic-v2/file-download/.mock/fern.config.json b/seed/pydantic-v2/file-download/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/file-download/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/file-download/.mock/generators.yml b/seed/pydantic-v2/file-download/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/file-download/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/file-download/snippet-templates.json b/seed/pydantic-v2/file-download/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/file-download/snippet.json b/seed/pydantic-v2/file-download/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/file-upload/.mock/definition/api.yml b/seed/pydantic-v2/file-upload/.mock/definition/api.yml new file mode 100644 index 00000000000..b7f420003fb --- /dev/null +++ b/seed/pydantic-v2/file-upload/.mock/definition/api.yml @@ -0,0 +1 @@ +name: file-upload diff --git a/seed/pydantic-v2/file-upload/.mock/definition/service.yml b/seed/pydantic-v2/file-upload/.mock/definition/service.yml new file mode 100644 index 00000000000..5ae95021c2d --- /dev/null +++ b/seed/pydantic-v2/file-upload/.mock/definition/service.yml @@ -0,0 +1,78 @@ +service: + auth: false + base-path: / + endpoints: + post: + path: "" + method: POST + request: + name: MyRequest + body: + properties: + maybeString: optional + integer: integer + file: file + fileList: list + maybeFile: optional + maybeFileList: optional> + maybeInteger: optional + optionalListOfStrings: optional> + listOfObjects: list + optionalMetadata: optional + optionalObjectType: optional + optionalId: optional + + justFile: + path: /just-file + method: POST + request: + name: JustFileRequet + body: + properties: + file: file + + justFileWithQueryParams: + path: /just-file-with-query-params + method: POST + request: + name: JustFileWithQueryParamsRequet + query-parameters: + maybeString: optional + integer: integer + maybeInteger: optional + listOfStrings: + type: string + allow-multiple: true + optionalListOfStrings: + type: optional + allow-multiple: true + body: + properties: + file: file + + withContentType: + path: "/with-content-type" + method: POST + request: + name: WithContentTypeRequest + body: + properties: + file: + type: file + content-type: application/octet-stream + foo: string + bar: + type: MyObject + content-type: application/json + +types: + Id: string + + MyObject: + properties: + foo: string + + ObjectType: + enum: + - FOO + - BAR \ No newline at end of file diff --git a/seed/pydantic-v2/file-upload/.mock/fern.config.json b/seed/pydantic-v2/file-upload/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/file-upload/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/file-upload/.mock/generators.yml b/seed/pydantic-v2/file-upload/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/file-upload/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/file-upload/resources/service/types/id.py b/seed/pydantic-v2/file-upload/resources/service/types/id.py new file mode 100644 index 00000000000..3f8f15db9d4 --- /dev/null +++ b/seed/pydantic-v2/file-upload/resources/service/types/id.py @@ -0,0 +1,19 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Id(RootModel[str]): + root: str + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: str) -> Id: + Id(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/file-upload/resources/service/types/my_object.py b/seed/pydantic-v2/file-upload/resources/service/types/my_object.py new file mode 100644 index 00000000000..b0d4b5e7e07 --- /dev/null +++ b/seed/pydantic-v2/file-upload/resources/service/types/my_object.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class MyObject(BaseModel): + foo: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/file-upload/snippet-templates.json b/seed/pydantic-v2/file-upload/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/file-upload/snippet.json b/seed/pydantic-v2/file-upload/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/folders/.mock/definition/__package__.yml b/seed/pydantic-v2/folders/.mock/definition/__package__.yml new file mode 100644 index 00000000000..e94d9e8e75a --- /dev/null +++ b/seed/pydantic-v2/folders/.mock/definition/__package__.yml @@ -0,0 +1,7 @@ +service: + base-path: / + auth: false + endpoints: + foo: + method: POST + path: "" diff --git a/seed/pydantic-v2/folders/.mock/definition/a/b/__package__.yml b/seed/pydantic-v2/folders/.mock/definition/a/b/__package__.yml new file mode 100644 index 00000000000..e94d9e8e75a --- /dev/null +++ b/seed/pydantic-v2/folders/.mock/definition/a/b/__package__.yml @@ -0,0 +1,7 @@ +service: + base-path: / + auth: false + endpoints: + foo: + method: POST + path: "" diff --git a/seed/pydantic-v2/folders/.mock/definition/a/c/__package__.yml b/seed/pydantic-v2/folders/.mock/definition/a/c/__package__.yml new file mode 100644 index 00000000000..e94d9e8e75a --- /dev/null +++ b/seed/pydantic-v2/folders/.mock/definition/a/c/__package__.yml @@ -0,0 +1,7 @@ +service: + base-path: / + auth: false + endpoints: + foo: + method: POST + path: "" diff --git a/seed/pydantic-v2/folders/.mock/definition/a/d/types.yml b/seed/pydantic-v2/folders/.mock/definition/a/d/types.yml new file mode 100644 index 00000000000..10d0cf8713d --- /dev/null +++ b/seed/pydantic-v2/folders/.mock/definition/a/d/types.yml @@ -0,0 +1,2 @@ +types: + Foo: string diff --git a/seed/pydantic-v2/folders/.mock/definition/api.yml b/seed/pydantic-v2/folders/.mock/definition/api.yml new file mode 100644 index 00000000000..9888645c477 --- /dev/null +++ b/seed/pydantic-v2/folders/.mock/definition/api.yml @@ -0,0 +1,4 @@ +name: api + +error-discrimination: + strategy: status-code diff --git a/seed/pydantic-v2/folders/.mock/definition/folder/__package__.yml b/seed/pydantic-v2/folders/.mock/definition/folder/__package__.yml new file mode 100644 index 00000000000..e94d9e8e75a --- /dev/null +++ b/seed/pydantic-v2/folders/.mock/definition/folder/__package__.yml @@ -0,0 +1,7 @@ +service: + base-path: / + auth: false + endpoints: + foo: + method: POST + path: "" diff --git a/seed/pydantic-v2/folders/.mock/definition/folder/service.yml b/seed/pydantic-v2/folders/.mock/definition/folder/service.yml new file mode 100644 index 00000000000..8c8a291592d --- /dev/null +++ b/seed/pydantic-v2/folders/.mock/definition/folder/service.yml @@ -0,0 +1,17 @@ +service: + base-path: /service + auth: false + endpoints: + endpoint: + method: GET + path: "" + unknownRequest: + method: POST + path: "" + request: unknown + errors: + - NotFoundError +errors: + NotFoundError: + status-code: 404 + type: string diff --git a/seed/pydantic-v2/folders/.mock/fern.config.json b/seed/pydantic-v2/folders/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/folders/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/folders/.mock/generators.yml b/seed/pydantic-v2/folders/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/folders/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/folders/resources/a/resources/d/resources/types/types/foo.py b/seed/pydantic-v2/folders/resources/a/resources/d/resources/types/types/foo.py new file mode 100644 index 00000000000..441e7fcc277 --- /dev/null +++ b/seed/pydantic-v2/folders/resources/a/resources/d/resources/types/types/foo.py @@ -0,0 +1,19 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Foo(RootModel[str]): + root: str + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: str) -> Foo: + Foo(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/folders/snippet-templates.json b/seed/pydantic-v2/folders/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/folders/snippet.json b/seed/pydantic-v2/folders/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/.mock/fern.config.json b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/.mock/generators.yml b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/generators.yml new file mode 100644 index 00000000000..972ed6d7b73 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/generators.yml @@ -0,0 +1,6 @@ +api: + - proto: + root: proto + target: proto/data/v1/data.proto + overrides: overrides.yml + local-generation: true \ No newline at end of file diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/.mock/overrides.yml b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/overrides.yml new file mode 100644 index 00000000000..062b98c2ccb --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/overrides.yml @@ -0,0 +1,56 @@ + +paths: + /data/fetch: + get: + x-fern-request-name: FetchRequest + /data/list: + get: + x-fern-request-name: ListRequest +components: + schemas: + Metadata: + oneOf: + - type: object + additionalProperties: + $ref: '#/components/schemas/MetadataValue' + - type: object + x-fern-encoding: + proto: + type: google.protobuf.Struct + MetadataValue: + oneOf: + - type: number + format: double + - type: string + - type: boolean + x-fern-encoding: + proto: + type: google.protobuf.Value + DeleteRequest: + properties: + filter: + $ref: '#/components/schemas/Metadata' + DescribeRequest: + properties: + filter: + $ref: '#/components/schemas/Metadata' + QueryRequest: + properties: + filter: + $ref: '#/components/schemas/Metadata' + QueryColumn: + properties: + filter: + $ref: '#/components/schemas/Metadata' + ScoredColumn: + properties: + metadata: + $ref: '#/components/schemas/Metadata' + UpdateRequest: + properties: + setMetadata: + $ref: '#/components/schemas/Metadata' + Column: + properties: + metadata: + $ref: '#/components/schemas/Metadata' \ No newline at end of file diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/data/v1/data.proto b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/data/v1/data.proto new file mode 100644 index 00000000000..dc3b07ece42 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/data/v1/data.proto @@ -0,0 +1,213 @@ +syntax = "proto3"; + +package data.v1; + +import "google/protobuf/struct.proto"; +import "google/api/annotations.proto"; +import "google/api/field_behavior.proto"; + +option csharp_namespace = "Data.V1.Grpc"; +option go_package = "github.com/acme.co/data-go-grpc"; + +message IndexedData { + repeated uint32 indices = 1 [ + (google.api.field_behavior) = REQUIRED + ]; + repeated float values = 2 [ + (google.api.field_behavior) = REQUIRED + ]; +} + +message Column { + string id = 1 [ + (google.api.field_behavior) = REQUIRED + ]; + repeated float values = 2 [ + (google.api.field_behavior) = REQUIRED + ]; + google.protobuf.Struct metadata = 3; + IndexedData indexed_data = 4; +} + +message ScoredColumn { + string id = 1 [ + (google.api.field_behavior) = REQUIRED + ]; + float score = 2; + repeated float values = 3; + google.protobuf.Struct metadata = 4; + IndexedData indexed_data = 5; +} + +message UploadRequest { + repeated Column columns = 1 [ + (google.api.field_behavior) = REQUIRED + ]; + string namespace = 2; +} + +message UploadResponse { + uint32 count = 1; +} + +message DeleteRequest { + repeated string ids = 1; + bool delete_all = 2; + string namespace = 3; + google.protobuf.Struct filter = 4; +} + +message DeleteResponse {} + +message FetchRequest { + repeated string ids = 1 [ + (google.api.field_behavior) = REQUIRED + ]; + string namespace = 2; +} + +message FetchResponse { + map columns = 1; + string namespace = 2; + optional Usage usage = 3; +} + +message ListRequest { + optional string prefix = 1; + optional uint32 limit = 2; + optional string pagination_token = 3; + string namespace = 4; +} + +message Pagination { + string next = 1; +} + +message ListElement { + string id = 1; +} + +message ListResponse { + repeated ListElement columns = 1; + optional Pagination pagination = 2; + string namespace = 3; + optional Usage usage = 4; +} + +message QueryColumn { + repeated float values = 1 [ + (google.api.field_behavior) = REQUIRED + ]; + uint32 top_k = 2; + string namespace = 3; + google.protobuf.Struct filter = 4; + IndexedData indexed_data = 5; +} + +message QueryRequest { + string namespace = 1; + uint32 top_k = 2 [ + (google.api.field_behavior) = REQUIRED + ]; + google.protobuf.Struct filter = 3; + bool include_values = 4; + bool include_metadata = 5; + repeated QueryColumn queries = 6 [ + deprecated = true + ]; + repeated float column = 7; + string id = 8; + IndexedData indexed_data = 9; +} + +message QueryResult { + repeated ScoredColumn matches = 1; + string namespace = 2; +} + +message QueryResponse { + repeated QueryResult results = 1 [deprecated=true]; + repeated ScoredColumn matches = 2; + string namespace = 3; + optional Usage usage = 4; +} + +message Usage { + optional uint32 units = 1; +} + +message UpdateRequest { + string id = 1 [ + (google.api.field_behavior) = REQUIRED + ]; + repeated float values = 2; + google.protobuf.Struct set_metadata = 3; + string namespace = 4; + IndexedData indexed_data = 5; +} + +message UpdateResponse {} + +message DescribeRequest { + google.protobuf.Struct filter = 1; +} + +message NamespaceSummary { + uint32 count = 1; +} + +message DescribeResponse { + map namespaces = 1; + uint32 dimension = 2; + float fullness = 3; + uint32 total_count = 4; +} + +service DataService { + rpc Upload(UploadRequest) returns (UploadResponse) { + option (google.api.http) = { + post: "/data" + body: "*" + }; + } + + rpc Delete(DeleteRequest) returns (DeleteResponse) { + option (google.api.http) = { + post: "/data/delete" + body: "*" + }; + } + + rpc Fetch(FetchRequest) returns (FetchResponse) { + option (google.api.http) = { + get: "/data/fetch" + }; + } + + rpc List(ListRequest) returns (ListResponse) { + option (google.api.http) = { + get: "/data/list" + }; + } + + rpc Query(QueryRequest) returns (QueryResponse) { + option (google.api.http) = { + post: "/data/query" + body: "*" + }; + } + + rpc Update(UpdateRequest) returns (UpdateResponse) { + option (google.api.http) = { + post: "/data/update" + body: "*" + }; + } + + rpc Describe(DescribeRequest) returns (DescribeResponse) { + option (google.api.http) = { + post: "/data/describe" + body: "*" + }; + } +} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/google/api/annotations.proto b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/google/api/annotations.proto new file mode 100644 index 00000000000..8ff42098404 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/google/api/annotations.proto @@ -0,0 +1,31 @@ +// Copyright 2015 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/http.proto"; +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // See `HttpRule`. + HttpRule http = 72295728; +} \ No newline at end of file diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/google/api/field_behavior.proto b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/google/api/field_behavior.proto new file mode 100644 index 00000000000..128799c558d --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/google/api/field_behavior.proto @@ -0,0 +1,104 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "FieldBehaviorProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.FieldOptions { + // A designation of a specific field behavior (required, output only, etc.) + // in protobuf messages. + // + // Examples: + // + // string name = 1 [(google.api.field_behavior) = REQUIRED]; + // State state = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; + // google.protobuf.Duration ttl = 1 + // [(google.api.field_behavior) = INPUT_ONLY]; + // google.protobuf.Timestamp expire_time = 1 + // [(google.api.field_behavior) = OUTPUT_ONLY, + // (google.api.field_behavior) = IMMUTABLE]; + repeated google.api.FieldBehavior field_behavior = 1052; +} + +// An indicator of the behavior of a given field (for example, that a field +// is required in requests, or given as output but ignored as input). +// This **does not** change the behavior in protocol buffers itself; it only +// denotes the behavior and may affect how API tooling handles the field. +// +// Note: This enum **may** receive new values in the future. +enum FieldBehavior { + // Conventional default for enums. Do not use this. + FIELD_BEHAVIOR_UNSPECIFIED = 0; + + // Specifically denotes a field as optional. + // While all fields in protocol buffers are optional, this may be specified + // for emphasis if appropriate. + OPTIONAL = 1; + + // Denotes a field as required. + // This indicates that the field **must** be provided as part of the request, + // and failure to do so will cause an error (usually `INVALID_ARGUMENT`). + REQUIRED = 2; + + // Denotes a field as output only. + // This indicates that the field is provided in responses, but including the + // field in a request does nothing (the server *must* ignore it and + // *must not* throw an error as a result of the field's presence). + OUTPUT_ONLY = 3; + + // Denotes a field as input only. + // This indicates that the field is provided in requests, and the + // corresponding field is not included in output. + INPUT_ONLY = 4; + + // Denotes a field as immutable. + // This indicates that the field may be set once in a request to create a + // resource, but may not be changed thereafter. + IMMUTABLE = 5; + + // Denotes that a (repeated) field is an unordered list. + // This indicates that the service may provide the elements of the list + // in any arbitrary order, rather than the order the user originally + // provided. Additionally, the list's order may or may not be stable. + UNORDERED_LIST = 6; + + // Denotes that this field returns a non-empty default value if not set. + // This indicates that if the user provides the empty value in a request, + // a non-empty value will be returned. The user will not be aware of what + // non-empty value to expect. + NON_EMPTY_DEFAULT = 7; + + // Denotes that the field in a resource (a message annotated with + // google.api.resource) is used in the resource name to uniquely identify the + // resource. For AIP-compliant APIs, this should only be applied to the + // `name` field on the resource. + // + // This behavior should not be applied to references to other resources within + // the message. + // + // The identifier field of resources often have different field behavior + // depending on the request it is embedded in (e.g. for Create methods name + // is optional and unused, while for Update methods it is required). Instead + // of method-specific annotations, only `IDENTIFIER` is required. + IDENTIFIER = 8; +} \ No newline at end of file diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/google/api/http.proto b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/google/api/http.proto new file mode 100644 index 00000000000..c8392381eb9 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/.mock/proto/google/api/http.proto @@ -0,0 +1,379 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Defines the HTTP configuration for an API service. It contains a list of +// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method +// to one or more HTTP REST API methods. +message Http { + // A list of HTTP configuration rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated HttpRule rules = 1; + + // When set to true, URL path parameters will be fully URI-decoded except in + // cases of single segment matches in reserved expansion, where "%2F" will be + // left encoded. + // + // The default behavior is to not decode RFC 6570 reserved characters in multi + // segment matches. + bool fully_decode_reserved_expansion = 2; +} + +// # gRPC Transcoding +// +// gRPC Transcoding is a feature for mapping between a gRPC method and one or +// more HTTP REST endpoints. It allows developers to build a single API service +// that supports both gRPC APIs and REST APIs. Many systems, including [Google +// APIs](https://github.com/googleapis/googleapis), +// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC +// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), +// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature +// and use it for large scale production services. +// +// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies +// how different portions of the gRPC request message are mapped to the URL +// path, URL query parameters, and HTTP request body. It also controls how the +// gRPC response message is mapped to the HTTP response body. `HttpRule` is +// typically specified as an `google.api.http` annotation on the gRPC method. +// +// Each mapping specifies a URL path template and an HTTP method. The path +// template may refer to one or more fields in the gRPC request message, as long +// as each field is a non-repeated field with a primitive (non-message) type. +// The path template controls how fields of the request message are mapped to +// the URL path. +// +// Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/{name=messages/*}" +// }; +// } +// } +// message GetMessageRequest { +// string name = 1; // Mapped to URL path. +// } +// message Message { +// string text = 1; // The resource content. +// } +// +// This enables an HTTP REST to gRPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` +// +// Any fields in the request message which are not bound by the path template +// automatically become HTTP query parameters if there is no HTTP request body. +// For example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get:"/v1/messages/{message_id}" +// }; +// } +// } +// message GetMessageRequest { +// message SubMessage { +// string subfield = 1; +// } +// string message_id = 1; // Mapped to URL path. +// int64 revision = 2; // Mapped to URL query parameter `revision`. +// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. +// } +// +// This enables a HTTP JSON to RPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | +// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: +// "foo"))` +// +// Note that fields which are mapped to URL query parameters must have a +// primitive type or a repeated primitive type or a non-repeated message type. +// In the case of a repeated type, the parameter can be repeated in the URL +// as `...?param=A¶m=B`. In the case of a message type, each field of the +// message is mapped to a separate parameter, such as +// `...?foo.a=A&foo.b=B&foo.c=C`. +// +// For HTTP methods that allow a request body, the `body` field +// specifies the mapping. Consider a REST update method on the +// message resource collection: +// +// service Messaging { +// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "message" +// }; +// } +// } +// message UpdateMessageRequest { +// string message_id = 1; // mapped to the URL +// Message message = 2; // mapped to the body +// } +// +// The following HTTP JSON to RPC mapping is enabled, where the +// representation of the JSON in the request body is determined by +// protos JSON encoding: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" message { text: "Hi!" })` +// +// The special name `*` can be used in the body mapping to define that +// every field not bound by the path template should be mapped to the +// request body. This enables the following alternative definition of +// the update method: +// +// service Messaging { +// rpc UpdateMessage(Message) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "*" +// }; +// } +// } +// message Message { +// string message_id = 1; +// string text = 2; +// } +// +// +// The following HTTP JSON to RPC mapping is enabled: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" text: "Hi!")` +// +// Note that when using `*` in the body mapping, it is not possible to +// have HTTP parameters, as all fields not bound by the path end in +// the body. This makes this option more rarely used in practice when +// defining REST APIs. The common usage of `*` is in custom methods +// which don't use the URL at all for transferring data. +// +// It is possible to define multiple HTTP methods for one RPC by using +// the `additional_bindings` option. Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/messages/{message_id}" +// additional_bindings { +// get: "/v1/users/{user_id}/messages/{message_id}" +// } +// }; +// } +// } +// message GetMessageRequest { +// string message_id = 1; +// string user_id = 2; +// } +// +// This enables the following two alternative HTTP JSON to RPC mappings: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` +// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: +// "123456")` +// +// ## Rules for HTTP mapping +// +// 1. Leaf request fields (recursive expansion nested messages in the request +// message) are classified into three categories: +// - Fields referred by the path template. They are passed via the URL path. +// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They +// are passed via the HTTP +// request body. +// - All other fields are passed via the URL query parameters, and the +// parameter name is the field path in the request message. A repeated +// field can be represented as multiple query parameters under the same +// name. +// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL +// query parameter, all fields +// are passed via URL path and HTTP request body. +// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP +// request body, all +// fields are passed via URL path and URL query parameters. +// +// ### Path template syntax +// +// Template = "/" Segments [ Verb ] ; +// Segments = Segment { "/" Segment } ; +// Segment = "*" | "**" | LITERAL | Variable ; +// Variable = "{" FieldPath [ "=" Segments ] "}" ; +// FieldPath = IDENT { "." IDENT } ; +// Verb = ":" LITERAL ; +// +// The syntax `*` matches a single URL path segment. The syntax `**` matches +// zero or more URL path segments, which must be the last part of the URL path +// except the `Verb`. +// +// The syntax `Variable` matches part of the URL path as specified by its +// template. A variable template must not contain other variables. If a variable +// matches a single path segment, its template may be omitted, e.g. `{var}` +// is equivalent to `{var=*}`. +// +// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` +// contains any reserved character, such characters should be percent-encoded +// before the matching. +// +// If a variable contains exactly one path segment, such as `"{var}"` or +// `"{var=*}"`, when such a variable is expanded into a URL path on the client +// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The +// server side does the reverse decoding. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{var}`. +// +// If a variable contains multiple path segments, such as `"{var=foo/*}"` +// or `"{var=**}"`, when such a variable is expanded into a URL path on the +// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. +// The server side does the reverse decoding, except "%2F" and "%2f" are left +// unchanged. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{+var}`. +// +// ## Using gRPC API Service Configuration +// +// gRPC API Service Configuration (service config) is a configuration language +// for configuring a gRPC service to become a user-facing product. The +// service config is simply the YAML representation of the `google.api.Service` +// proto message. +// +// As an alternative to annotating your proto file, you can configure gRPC +// transcoding in your service config YAML files. You do this by specifying a +// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same +// effect as the proto annotation. This can be particularly useful if you +// have a proto that is reused in multiple services. Note that any transcoding +// specified in the service config will override any matching transcoding +// configuration in the proto. +// +// Example: +// +// http: +// rules: +// # Selects a gRPC method and applies HttpRule to it. +// - selector: example.v1.Messaging.GetMessage +// get: /v1/messages/{message_id}/{sub.subfield} +// +// ## Special notes +// +// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the +// proto to JSON conversion must follow the [proto3 +// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). +// +// While the single segment variable follows the semantics of +// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String +// Expansion, the multi segment variable **does not** follow RFC 6570 Section +// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion +// does not expand special characters like `?` and `#`, which would lead +// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding +// for multi segment variables. +// +// The path variables **must not** refer to any repeated or mapped field, +// because client libraries are not capable of handling such variable expansion. +// +// The path variables **must not** capture the leading "/" character. The reason +// is that the most common use case "{var}" does not capture the leading "/" +// character. For consistency, all path variables must share the same behavior. +// +// Repeated message fields must not be mapped to URL query parameters, because +// no client library can support such complicated mapping. +// +// If an API needs to use a JSON array for request or response body, it can map +// the request or response body to a repeated field. However, some gRPC +// Transcoding implementations may not support this feature. +message HttpRule { + // Selects a method to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // Determines the URL pattern is matched by this rules. This pattern can be + // used with any of the {get|put|post|delete|patch} methods. A custom method + // can be defined using the 'custom' field. + oneof pattern { + // Maps to HTTP GET. Used for listing and getting information about + // resources. + string get = 2; + + // Maps to HTTP PUT. Used for replacing a resource. + string put = 3; + + // Maps to HTTP POST. Used for creating a resource or performing an action. + string post = 4; + + // Maps to HTTP DELETE. Used for deleting a resource. + string delete = 5; + + // Maps to HTTP PATCH. Used for updating a resource. + string patch = 6; + + // The custom pattern is used for specifying an HTTP method that is not + // included in the `pattern` field, such as HEAD, or "*" to leave the + // HTTP method unspecified for this rule. The wild-card rule is useful + // for services that provide content to Web (HTML) clients. + CustomHttpPattern custom = 8; + } + + // The name of the request field whose value is mapped to the HTTP request + // body, or `*` for mapping all request fields not captured by the path + // pattern to the HTTP body, or omitted for not having any HTTP request body. + // + // NOTE: the referred field must be present at the top-level of the request + // message type. + string body = 7; + + // Optional. The name of the response field whose value is mapped to the HTTP + // response body. When omitted, the entire response message will be used + // as the HTTP response body. + // + // NOTE: The referred field must be present at the top-level of the response + // message type. + string response_body = 12; + + // Additional HTTP bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + repeated HttpRule additional_bindings = 11; +} + +// A custom pattern is used for defining custom HTTP verb. +message CustomHttpPattern { + // The name of this custom HTTP verb. + string kind = 1; + + // The path matched by this custom verb. + string path = 2; +} \ No newline at end of file diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/snippet-templates.json b/seed/pydantic-v2/grpc-proto-exhaustive/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/snippet.json b/seed/pydantic-v2/grpc-proto-exhaustive/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/column.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/column.py new file mode 100644 index 00000000000..8b4cf0a463c --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/column.py @@ -0,0 +1,18 @@ +from pydantic import BaseModel +from typing import List, Optional +from .types.metadata import Metadata +from .types.indexed_data import IndexedData +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Column(BaseModel): + id: str + values: List[float] + metadata: Optional[Metadata] = None + indexed_data: Optional[IndexedData] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/delete_response.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/delete_response.py new file mode 100644 index 00000000000..305bd059f6b --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/delete_response.py @@ -0,0 +1,10 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class DeleteResponse(BaseModel): + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/describe_response.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/describe_response.py new file mode 100644 index 00000000000..c75169dec33 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/describe_response.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel +from typing import Optional, Dict +from .types.namespace_summary import NamespaceSummary +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class DescribeResponse(BaseModel): + namespaces: Optional[Dict[str, NamespaceSummary]] = None + dimension: Optional[int] = None + fullness: Optional[float] = None + total_count: Optional[int] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/fetch_response.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/fetch_response.py new file mode 100644 index 00000000000..f7f9cbff3f3 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/fetch_response.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel +from typing import Optional, Dict +from .types.column import Column +from .types.usage import Usage +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class FetchResponse(BaseModel): + columns: Optional[Dict[str, Column]] = None + namespace: Optional[str] = None + usage: Optional[Usage] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/indexed_data.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/indexed_data.py new file mode 100644 index 00000000000..2d9de61c7c3 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/indexed_data.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import List +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class IndexedData(BaseModel): + indices: List[int] + values: List[float] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/list_element.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/list_element.py new file mode 100644 index 00000000000..b976fc1d997 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/list_element.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ListElement(BaseModel): + id: Optional[str] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/list_response.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/list_response.py new file mode 100644 index 00000000000..3e443d579aa --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/list_response.py @@ -0,0 +1,19 @@ +from pydantic import BaseModel +from typing import Optional, List +from .types.list_element import ListElement +from .types.pagination import Pagination +from .types.usage import Usage +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ListResponse(BaseModel): + columns: Optional[List[ListElement]] = None + pagination: Optional[Pagination] = None + namespace: Optional[str] = None + usage: Optional[Usage] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/namespace_summary.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/namespace_summary.py new file mode 100644 index 00000000000..4f3916693d9 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/namespace_summary.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class NamespaceSummary(BaseModel): + count: Optional[int] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/pagination.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/pagination.py new file mode 100644 index 00000000000..aee7d1f9dd0 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/pagination.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Pagination(BaseModel): + next: Optional[str] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/query_column.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/query_column.py new file mode 100644 index 00000000000..e6fab001451 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/query_column.py @@ -0,0 +1,19 @@ +from pydantic import BaseModel +from typing import List, Optional +from .types.metadata import Metadata +from .types.indexed_data import IndexedData +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class QueryColumn(BaseModel): + values: List[float] + top_k: Optional[int] + namespace: Optional[str] = None + filter: Optional[Metadata] = None + indexed_data: Optional[IndexedData] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/query_response.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/query_response.py new file mode 100644 index 00000000000..39f3af2268d --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/query_response.py @@ -0,0 +1,19 @@ +from pydantic import BaseModel +from typing import Optional, List +from .types.query_result import QueryResult +from .types.scored_column import ScoredColumn +from .types.usage import Usage +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class QueryResponse(BaseModel): + results: Optional[List[QueryResult]] = None + matches: Optional[List[ScoredColumn]] = None + namespace: Optional[str] = None + usage: Optional[Usage] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/query_result.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/query_result.py new file mode 100644 index 00000000000..47b8d984e60 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/query_result.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel +from typing import Optional, List +from .types.scored_column import ScoredColumn +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class QueryResult(BaseModel): + matches: Optional[List[ScoredColumn]] = None + namespace: Optional[str] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/scored_column.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/scored_column.py new file mode 100644 index 00000000000..31c75d88fdc --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/scored_column.py @@ -0,0 +1,19 @@ +from pydantic import BaseModel +from typing import Optional, List +from .types.metadata import Metadata +from .types.indexed_data import IndexedData +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ScoredColumn(BaseModel): + id: str + score: Optional[float] = None + values: Optional[List[float]] = None + metadata: Optional[Metadata] = None + indexed_data: Optional[IndexedData] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/update_response.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/update_response.py new file mode 100644 index 00000000000..8cb6344fb5d --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/update_response.py @@ -0,0 +1,10 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UpdateResponse(BaseModel): + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/upload_response.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/upload_response.py new file mode 100644 index 00000000000..70453a37d3b --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/upload_response.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UploadResponse(BaseModel): + count: Optional[int] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto-exhaustive/types/usage.py b/seed/pydantic-v2/grpc-proto-exhaustive/types/usage.py new file mode 100644 index 00000000000..f70ca4fe3b5 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto-exhaustive/types/usage.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Usage(BaseModel): + units: Optional[int] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto/.mock/fern.config.json b/seed/pydantic-v2/grpc-proto/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/grpc-proto/.mock/generators.yml b/seed/pydantic-v2/grpc-proto/.mock/generators.yml new file mode 100644 index 00000000000..d6b509d39ea --- /dev/null +++ b/seed/pydantic-v2/grpc-proto/.mock/generators.yml @@ -0,0 +1,6 @@ +api: + - proto: + root: proto + target: proto/user/v1/user.proto + overrides: overrides.yml + local-generation: true \ No newline at end of file diff --git a/seed/pydantic-v2/grpc-proto/.mock/overrides.yml b/seed/pydantic-v2/grpc-proto/.mock/overrides.yml new file mode 100644 index 00000000000..bb6db99b0e4 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto/.mock/overrides.yml @@ -0,0 +1,31 @@ +components: + schemas: + UserModel: + properties: + metadata: + $ref: '#/components/schemas/Metadata' + + CreateRequest: + properties: + metadata: + $ref: '#/components/schemas/Metadata' + + Metadata: + oneOf: + - type: object + additionalProperties: + $ref: '#/components/schemas/MetadataValue' + - type: object + x-fern-encoding: + proto: + type: google.protobuf.Struct + + MetadataValue: + oneOf: + - type: number + format: double + - type: string + - type: boolean + x-fern-encoding: + proto: + type: google.protobuf.Value diff --git a/seed/pydantic-v2/grpc-proto/.mock/proto/google/api/annotations.proto b/seed/pydantic-v2/grpc-proto/.mock/proto/google/api/annotations.proto new file mode 100644 index 00000000000..8ff42098404 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto/.mock/proto/google/api/annotations.proto @@ -0,0 +1,31 @@ +// Copyright 2015 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/http.proto"; +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // See `HttpRule`. + HttpRule http = 72295728; +} \ No newline at end of file diff --git a/seed/pydantic-v2/grpc-proto/.mock/proto/google/api/http.proto b/seed/pydantic-v2/grpc-proto/.mock/proto/google/api/http.proto new file mode 100644 index 00000000000..c8392381eb9 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto/.mock/proto/google/api/http.proto @@ -0,0 +1,379 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Defines the HTTP configuration for an API service. It contains a list of +// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method +// to one or more HTTP REST API methods. +message Http { + // A list of HTTP configuration rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated HttpRule rules = 1; + + // When set to true, URL path parameters will be fully URI-decoded except in + // cases of single segment matches in reserved expansion, where "%2F" will be + // left encoded. + // + // The default behavior is to not decode RFC 6570 reserved characters in multi + // segment matches. + bool fully_decode_reserved_expansion = 2; +} + +// # gRPC Transcoding +// +// gRPC Transcoding is a feature for mapping between a gRPC method and one or +// more HTTP REST endpoints. It allows developers to build a single API service +// that supports both gRPC APIs and REST APIs. Many systems, including [Google +// APIs](https://github.com/googleapis/googleapis), +// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC +// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), +// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature +// and use it for large scale production services. +// +// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies +// how different portions of the gRPC request message are mapped to the URL +// path, URL query parameters, and HTTP request body. It also controls how the +// gRPC response message is mapped to the HTTP response body. `HttpRule` is +// typically specified as an `google.api.http` annotation on the gRPC method. +// +// Each mapping specifies a URL path template and an HTTP method. The path +// template may refer to one or more fields in the gRPC request message, as long +// as each field is a non-repeated field with a primitive (non-message) type. +// The path template controls how fields of the request message are mapped to +// the URL path. +// +// Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/{name=messages/*}" +// }; +// } +// } +// message GetMessageRequest { +// string name = 1; // Mapped to URL path. +// } +// message Message { +// string text = 1; // The resource content. +// } +// +// This enables an HTTP REST to gRPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` +// +// Any fields in the request message which are not bound by the path template +// automatically become HTTP query parameters if there is no HTTP request body. +// For example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get:"/v1/messages/{message_id}" +// }; +// } +// } +// message GetMessageRequest { +// message SubMessage { +// string subfield = 1; +// } +// string message_id = 1; // Mapped to URL path. +// int64 revision = 2; // Mapped to URL query parameter `revision`. +// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. +// } +// +// This enables a HTTP JSON to RPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | +// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: +// "foo"))` +// +// Note that fields which are mapped to URL query parameters must have a +// primitive type or a repeated primitive type or a non-repeated message type. +// In the case of a repeated type, the parameter can be repeated in the URL +// as `...?param=A¶m=B`. In the case of a message type, each field of the +// message is mapped to a separate parameter, such as +// `...?foo.a=A&foo.b=B&foo.c=C`. +// +// For HTTP methods that allow a request body, the `body` field +// specifies the mapping. Consider a REST update method on the +// message resource collection: +// +// service Messaging { +// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "message" +// }; +// } +// } +// message UpdateMessageRequest { +// string message_id = 1; // mapped to the URL +// Message message = 2; // mapped to the body +// } +// +// The following HTTP JSON to RPC mapping is enabled, where the +// representation of the JSON in the request body is determined by +// protos JSON encoding: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" message { text: "Hi!" })` +// +// The special name `*` can be used in the body mapping to define that +// every field not bound by the path template should be mapped to the +// request body. This enables the following alternative definition of +// the update method: +// +// service Messaging { +// rpc UpdateMessage(Message) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "*" +// }; +// } +// } +// message Message { +// string message_id = 1; +// string text = 2; +// } +// +// +// The following HTTP JSON to RPC mapping is enabled: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" text: "Hi!")` +// +// Note that when using `*` in the body mapping, it is not possible to +// have HTTP parameters, as all fields not bound by the path end in +// the body. This makes this option more rarely used in practice when +// defining REST APIs. The common usage of `*` is in custom methods +// which don't use the URL at all for transferring data. +// +// It is possible to define multiple HTTP methods for one RPC by using +// the `additional_bindings` option. Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/messages/{message_id}" +// additional_bindings { +// get: "/v1/users/{user_id}/messages/{message_id}" +// } +// }; +// } +// } +// message GetMessageRequest { +// string message_id = 1; +// string user_id = 2; +// } +// +// This enables the following two alternative HTTP JSON to RPC mappings: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` +// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: +// "123456")` +// +// ## Rules for HTTP mapping +// +// 1. Leaf request fields (recursive expansion nested messages in the request +// message) are classified into three categories: +// - Fields referred by the path template. They are passed via the URL path. +// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They +// are passed via the HTTP +// request body. +// - All other fields are passed via the URL query parameters, and the +// parameter name is the field path in the request message. A repeated +// field can be represented as multiple query parameters under the same +// name. +// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL +// query parameter, all fields +// are passed via URL path and HTTP request body. +// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP +// request body, all +// fields are passed via URL path and URL query parameters. +// +// ### Path template syntax +// +// Template = "/" Segments [ Verb ] ; +// Segments = Segment { "/" Segment } ; +// Segment = "*" | "**" | LITERAL | Variable ; +// Variable = "{" FieldPath [ "=" Segments ] "}" ; +// FieldPath = IDENT { "." IDENT } ; +// Verb = ":" LITERAL ; +// +// The syntax `*` matches a single URL path segment. The syntax `**` matches +// zero or more URL path segments, which must be the last part of the URL path +// except the `Verb`. +// +// The syntax `Variable` matches part of the URL path as specified by its +// template. A variable template must not contain other variables. If a variable +// matches a single path segment, its template may be omitted, e.g. `{var}` +// is equivalent to `{var=*}`. +// +// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` +// contains any reserved character, such characters should be percent-encoded +// before the matching. +// +// If a variable contains exactly one path segment, such as `"{var}"` or +// `"{var=*}"`, when such a variable is expanded into a URL path on the client +// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The +// server side does the reverse decoding. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{var}`. +// +// If a variable contains multiple path segments, such as `"{var=foo/*}"` +// or `"{var=**}"`, when such a variable is expanded into a URL path on the +// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. +// The server side does the reverse decoding, except "%2F" and "%2f" are left +// unchanged. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{+var}`. +// +// ## Using gRPC API Service Configuration +// +// gRPC API Service Configuration (service config) is a configuration language +// for configuring a gRPC service to become a user-facing product. The +// service config is simply the YAML representation of the `google.api.Service` +// proto message. +// +// As an alternative to annotating your proto file, you can configure gRPC +// transcoding in your service config YAML files. You do this by specifying a +// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same +// effect as the proto annotation. This can be particularly useful if you +// have a proto that is reused in multiple services. Note that any transcoding +// specified in the service config will override any matching transcoding +// configuration in the proto. +// +// Example: +// +// http: +// rules: +// # Selects a gRPC method and applies HttpRule to it. +// - selector: example.v1.Messaging.GetMessage +// get: /v1/messages/{message_id}/{sub.subfield} +// +// ## Special notes +// +// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the +// proto to JSON conversion must follow the [proto3 +// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). +// +// While the single segment variable follows the semantics of +// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String +// Expansion, the multi segment variable **does not** follow RFC 6570 Section +// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion +// does not expand special characters like `?` and `#`, which would lead +// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding +// for multi segment variables. +// +// The path variables **must not** refer to any repeated or mapped field, +// because client libraries are not capable of handling such variable expansion. +// +// The path variables **must not** capture the leading "/" character. The reason +// is that the most common use case "{var}" does not capture the leading "/" +// character. For consistency, all path variables must share the same behavior. +// +// Repeated message fields must not be mapped to URL query parameters, because +// no client library can support such complicated mapping. +// +// If an API needs to use a JSON array for request or response body, it can map +// the request or response body to a repeated field. However, some gRPC +// Transcoding implementations may not support this feature. +message HttpRule { + // Selects a method to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // Determines the URL pattern is matched by this rules. This pattern can be + // used with any of the {get|put|post|delete|patch} methods. A custom method + // can be defined using the 'custom' field. + oneof pattern { + // Maps to HTTP GET. Used for listing and getting information about + // resources. + string get = 2; + + // Maps to HTTP PUT. Used for replacing a resource. + string put = 3; + + // Maps to HTTP POST. Used for creating a resource or performing an action. + string post = 4; + + // Maps to HTTP DELETE. Used for deleting a resource. + string delete = 5; + + // Maps to HTTP PATCH. Used for updating a resource. + string patch = 6; + + // The custom pattern is used for specifying an HTTP method that is not + // included in the `pattern` field, such as HEAD, or "*" to leave the + // HTTP method unspecified for this rule. The wild-card rule is useful + // for services that provide content to Web (HTML) clients. + CustomHttpPattern custom = 8; + } + + // The name of the request field whose value is mapped to the HTTP request + // body, or `*` for mapping all request fields not captured by the path + // pattern to the HTTP body, or omitted for not having any HTTP request body. + // + // NOTE: the referred field must be present at the top-level of the request + // message type. + string body = 7; + + // Optional. The name of the response field whose value is mapped to the HTTP + // response body. When omitted, the entire response message will be used + // as the HTTP response body. + // + // NOTE: The referred field must be present at the top-level of the response + // message type. + string response_body = 12; + + // Additional HTTP bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + repeated HttpRule additional_bindings = 11; +} + +// A custom pattern is used for defining custom HTTP verb. +message CustomHttpPattern { + // The name of this custom HTTP verb. + string kind = 1; + + // The path matched by this custom verb. + string path = 2; +} \ No newline at end of file diff --git a/seed/pydantic-v2/grpc-proto/.mock/proto/user/v1/user.proto b/seed/pydantic-v2/grpc-proto/.mock/proto/user/v1/user.proto new file mode 100644 index 00000000000..28542ac965a --- /dev/null +++ b/seed/pydantic-v2/grpc-proto/.mock/proto/user/v1/user.proto @@ -0,0 +1,38 @@ +syntax = "proto3"; + +package user.v1; + +import "google/api/annotations.proto"; +import "google/protobuf/struct.proto"; + +option csharp_namespace = "User.V1"; +option go_package = "user/v1"; + +message UserModel { + string username = 1; + string email = 2; + uint32 age = 3; + float weight = 4; + google.protobuf.Struct metadata = 5; +} + +message CreateRequest { + string username = 1; + string email = 2; + uint32 age = 3; + float weight = 4; + google.protobuf.Struct metadata = 5; +} + +message CreateResponse { + UserModel user = 1; +} + +service UserService { + rpc Create(CreateRequest) returns (CreateResponse) { + option (google.api.http) = { + post: "/users" + body: "*" + }; + } +} \ No newline at end of file diff --git a/seed/pydantic-v2/grpc-proto/snippet-templates.json b/seed/pydantic-v2/grpc-proto/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/grpc-proto/snippet.json b/seed/pydantic-v2/grpc-proto/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/grpc-proto/types/create_response.py b/seed/pydantic-v2/grpc-proto/types/create_response.py new file mode 100644 index 00000000000..d873069f64d --- /dev/null +++ b/seed/pydantic-v2/grpc-proto/types/create_response.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from .types.user_model import UserModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class CreateResponse(BaseModel): + user: Optional[UserModel] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/grpc-proto/types/user_model.py b/seed/pydantic-v2/grpc-proto/types/user_model.py new file mode 100644 index 00000000000..df694614716 --- /dev/null +++ b/seed/pydantic-v2/grpc-proto/types/user_model.py @@ -0,0 +1,18 @@ +from pydantic import BaseModel +from typing import Optional +from .types.metadata import Metadata +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UserModel(BaseModel): + username: Optional[str] = None + email: Optional[str] = None + age: Optional[int] = None + weight: Optional[float] = None + metadata: Optional[Metadata] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/idempotency-headers/.mock/definition/api.yml b/seed/pydantic-v2/idempotency-headers/.mock/definition/api.yml new file mode 100644 index 00000000000..7fbd5ce078b --- /dev/null +++ b/seed/pydantic-v2/idempotency-headers/.mock/definition/api.yml @@ -0,0 +1,5 @@ +name: idempotency-headers +auth: bearer +idempotency-headers: + Idempotency-Key: string + Idempotency-Expiration: integer diff --git a/seed/pydantic-v2/idempotency-headers/.mock/definition/payment.yml b/seed/pydantic-v2/idempotency-headers/.mock/definition/payment.yml new file mode 100644 index 00000000000..d8eb6950460 --- /dev/null +++ b/seed/pydantic-v2/idempotency-headers/.mock/definition/payment.yml @@ -0,0 +1,27 @@ +types: + Currency: + enum: + - USD + - YEN + +service: + auth: true + base-path: /payment + endpoints: + create: + method: POST + path: "" + idempotent: true + request: + name: CreatePaymentRequest + body: + properties: + amount: integer + currency: Currency + response: uuid + + delete: + method: DELETE + path: /{paymentId} + path-parameters: + paymentId: string diff --git a/seed/pydantic-v2/idempotency-headers/.mock/fern.config.json b/seed/pydantic-v2/idempotency-headers/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/idempotency-headers/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/idempotency-headers/.mock/generators.yml b/seed/pydantic-v2/idempotency-headers/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/idempotency-headers/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/idempotency-headers/snippet-templates.json b/seed/pydantic-v2/idempotency-headers/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/idempotency-headers/snippet.json b/seed/pydantic-v2/idempotency-headers/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/imdb/.mock/definition/api.yml b/seed/pydantic-v2/imdb/.mock/definition/api.yml new file mode 100644 index 00000000000..c437dc0ab29 --- /dev/null +++ b/seed/pydantic-v2/imdb/.mock/definition/api.yml @@ -0,0 +1,4 @@ +name: api +error-discrimination: + strategy: status-code +auth: bearer diff --git a/seed/pydantic-v2/imdb/.mock/definition/imdb.yml b/seed/pydantic-v2/imdb/.mock/definition/imdb.yml new file mode 100644 index 00000000000..7919173fe57 --- /dev/null +++ b/seed/pydantic-v2/imdb/.mock/definition/imdb.yml @@ -0,0 +1,42 @@ +types: + MovieId: string + + Movie: + properties: + id: MovieId + title: string + rating: + type: double + docs: The rating scale is one to five stars + + CreateMovieRequest: + properties: + title: string + rating: double + +service: + auth: false + base-path: /movies + endpoints: + createMovie: + docs: Add a movie to the database + method: POST + path: /create-movie + request: CreateMovieRequest + response: + type: MovieId + status-code: 201 + + getMovie: + method: GET + path: /{movieId} + path-parameters: + movieId: MovieId + response: Movie + errors: + - MovieDoesNotExistError + +errors: + MovieDoesNotExistError: + status-code: 404 + type: MovieId diff --git a/seed/pydantic-v2/imdb/.mock/fern.config.json b/seed/pydantic-v2/imdb/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/imdb/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/imdb/.mock/generators.yml b/seed/pydantic-v2/imdb/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/imdb/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/imdb/resources/imdb/types/create_movie_request.py b/seed/pydantic-v2/imdb/resources/imdb/types/create_movie_request.py new file mode 100644 index 00000000000..29d65f7cf32 --- /dev/null +++ b/seed/pydantic-v2/imdb/resources/imdb/types/create_movie_request.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class CreateMovieRequest(BaseModel): + title: str + rating: float + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/imdb/resources/imdb/types/movie.py b/seed/pydantic-v2/imdb/resources/imdb/types/movie.py new file mode 100644 index 00000000000..077831a0e7c --- /dev/null +++ b/seed/pydantic-v2/imdb/resources/imdb/types/movie.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Movie(BaseModel): + id: str + title: str + rating: float + """ + The rating scale is one to five stars + """ + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/imdb/resources/imdb/types/movie_id.py b/seed/pydantic-v2/imdb/resources/imdb/types/movie_id.py new file mode 100644 index 00000000000..d18d5e6749e --- /dev/null +++ b/seed/pydantic-v2/imdb/resources/imdb/types/movie_id.py @@ -0,0 +1,19 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class MovieId(RootModel[str]): + root: str + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: str) -> MovieId: + MovieId(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/imdb/snippet-templates.json b/seed/pydantic-v2/imdb/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/imdb/snippet.json b/seed/pydantic-v2/imdb/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/literal/.mock/definition/__package__.yml b/seed/pydantic-v2/literal/.mock/definition/__package__.yml new file mode 100644 index 00000000000..9247629c4d5 --- /dev/null +++ b/seed/pydantic-v2/literal/.mock/definition/__package__.yml @@ -0,0 +1,10 @@ +types: + SendResponse: + properties: + message: + type: string + status: + type: integer + success: + type: literal + \ No newline at end of file diff --git a/seed/pydantic-v2/literal/.mock/definition/api.yml b/seed/pydantic-v2/literal/.mock/definition/api.yml new file mode 100644 index 00000000000..d3b137fcece --- /dev/null +++ b/seed/pydantic-v2/literal/.mock/definition/api.yml @@ -0,0 +1,10 @@ +name: literal +docs: | + Test definition for literal schemas. +headers: + X-API-Version: + name: version + type: literal<"02-02-2024"> + X-API-Enable-Audit-Logging: + name: audit_logging + type: literal \ No newline at end of file diff --git a/seed/pydantic-v2/literal/.mock/definition/headers.yml b/seed/pydantic-v2/literal/.mock/definition/headers.yml new file mode 100644 index 00000000000..1b7e148d61a --- /dev/null +++ b/seed/pydantic-v2/literal/.mock/definition/headers.yml @@ -0,0 +1,36 @@ +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + send: + path: /headers + method: POST + request: + name: SendLiteralsInHeadersRequest + headers: + X-Endpoint-Version: + name: endpointVersion + type: literal<"02-12-2024"> + X-Async: + name: async + type: literal + body: + properties: + query: + type: string + response: root.SendResponse + examples: + - headers: + X-Endpoint-Version: "02-12-2024" + X-Async: true + request: + query: "What is the weather today" + response: + body: + message: "The weather is sunny" + status: 200 + success: true + \ No newline at end of file diff --git a/seed/pydantic-v2/literal/.mock/definition/inlined.yml b/seed/pydantic-v2/literal/.mock/definition/inlined.yml new file mode 100644 index 00000000000..c2834c5c50c --- /dev/null +++ b/seed/pydantic-v2/literal/.mock/definition/inlined.yml @@ -0,0 +1,53 @@ +imports: + root: __package__.yml + +types: + SomeAliasedLiteral: + type: literal<"You're super wise"> + + ATopLevelLiteral: + properties: + nestedLiteral: ANestedLiteral + + ANestedLiteral: + properties: + myLiteral: literal<"How super cool"> + +service: + auth: false + base-path: "" + endpoints: + send: + path: /inlined + method: POST + request: + name: SendLiteralsInlinedRequest + body: + properties: + prompt: literal<"You are a helpful assistant"> + context: optional> + query: string + temperature: optional + stream: literal + aliasedContext: SomeAliasedLiteral + maybeContext: optional + objectWithLiteral: ATopLevelLiteral + + response: root.SendResponse + examples: + - request: + temperature: 10.1 + prompt: "You are a helpful assistant" + context: "You're super wise" + aliasedContext: "You're super wise" + maybeContext: "You're super wise" + objectWithLiteral: + nestedLiteral: + myLiteral: "How super cool" + stream: false + query: "What is the weather today" + response: + body: + message: "The weather is sunny" + status: 200 + success: true diff --git a/seed/pydantic-v2/literal/.mock/definition/path.yml b/seed/pydantic-v2/literal/.mock/definition/path.yml new file mode 100644 index 00000000000..236d8744417 --- /dev/null +++ b/seed/pydantic-v2/literal/.mock/definition/path.yml @@ -0,0 +1,22 @@ +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + send: + path: /path/{id} + method: POST + path-parameters: + id: literal<"123"> + response: root.SendResponse + examples: + - path-parameters: + id: "123" + response: + body: + message: "The weather is sunny" + status: 200 + success: true + \ No newline at end of file diff --git a/seed/pydantic-v2/literal/.mock/definition/query.yml b/seed/pydantic-v2/literal/.mock/definition/query.yml new file mode 100644 index 00000000000..9d6cec5ad8e --- /dev/null +++ b/seed/pydantic-v2/literal/.mock/definition/query.yml @@ -0,0 +1,28 @@ +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + send: + path: /query + method: POST + request: + name: SendLiteralsInQueryRequest + query-parameters: + prompt: literal<"You are a helpful assistant"> + query: string + stream: literal + response: root.SendResponse + examples: + - query-parameters: + prompt: "You are a helpful assistant" + stream: false + query: "What is the weather today" + response: + body: + message: "The weather is sunny" + status: 200 + success: true + \ No newline at end of file diff --git a/seed/pydantic-v2/literal/.mock/definition/reference.yml b/seed/pydantic-v2/literal/.mock/definition/reference.yml new file mode 100644 index 00000000000..ec164521928 --- /dev/null +++ b/seed/pydantic-v2/literal/.mock/definition/reference.yml @@ -0,0 +1,48 @@ +imports: + root: __package__.yml + +types: + SendRequest: + properties: + prompt: literal<"You are a helpful assistant"> + query: string + stream: literal + context: SomeLiteral + maybeContext: optional + containerObject: ContainerObject + ContainerObject: + properties: + nestedObjects: list + NestedObjectWithLiterals: + properties: + literal1: literal<"literal1"> + literal2: literal<"literal2"> + strProp: string + SomeLiteral: + type: literal<"You're super wise"> + +service: + auth: false + base-path: "" + endpoints: + send: + path: /reference + method: POST + request: SendRequest + response: root.SendResponse + examples: + - request: + prompt: "You are a helpful assistant" + stream: false + context: "You're super wise" + query: "What is the weather today" + containerObject: + nestedObjects: + - literal1: "literal1" + literal2: "literal2" + strProp: "strProp" + response: + body: + message: "The weather is sunny" + status: 200 + success: true diff --git a/seed/pydantic-v2/literal/.mock/fern.config.json b/seed/pydantic-v2/literal/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/literal/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/literal/.mock/generators.yml b/seed/pydantic-v2/literal/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/literal/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/literal/resources/inlined/types/a_nested_literal.py b/seed/pydantic-v2/literal/resources/inlined/types/a_nested_literal.py new file mode 100644 index 00000000000..e8535566a07 --- /dev/null +++ b/seed/pydantic-v2/literal/resources/inlined/types/a_nested_literal.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ANestedLiteral(BaseModel): + my_literal: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/literal/resources/inlined/types/a_top_level_literal.py b/seed/pydantic-v2/literal/resources/inlined/types/a_top_level_literal.py new file mode 100644 index 00000000000..93d7956ced9 --- /dev/null +++ b/seed/pydantic-v2/literal/resources/inlined/types/a_top_level_literal.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from resources.inlined.types.a_nested_literal import ANestedLiteral +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ATopLevelLiteral(BaseModel): + nested_literal: ANestedLiteral + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/literal/resources/inlined/types/some_aliased_literal.py b/seed/pydantic-v2/literal/resources/inlined/types/some_aliased_literal.py new file mode 100644 index 00000000000..fda7cff6b9b --- /dev/null +++ b/seed/pydantic-v2/literal/resources/inlined/types/some_aliased_literal.py @@ -0,0 +1,19 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class SomeAliasedLiteral(RootModel[str]): + root: str + + def get_as_string() -> UUID: + return self.root + + @staticmethod + def from_string(value: str) -> SomeAliasedLiteral: + SomeAliasedLiteral(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/literal/resources/reference/types/container_object.py b/seed/pydantic-v2/literal/resources/reference/types/container_object.py new file mode 100644 index 00000000000..f8666009cac --- /dev/null +++ b/seed/pydantic-v2/literal/resources/reference/types/container_object.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel +from typing import List +from resources.reference.types.nested_object_with_literals import ( + NestedObjectWithLiterals, +) +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ContainerObject(BaseModel): + nested_objects: List[NestedObjectWithLiterals] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/literal/resources/reference/types/nested_object_with_literals.py b/seed/pydantic-v2/literal/resources/reference/types/nested_object_with_literals.py new file mode 100644 index 00000000000..9f42c1c7de3 --- /dev/null +++ b/seed/pydantic-v2/literal/resources/reference/types/nested_object_with_literals.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class NestedObjectWithLiterals(BaseModel): + literal_1: str + literal_2: str + str_prop: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/literal/resources/reference/types/send_request.py b/seed/pydantic-v2/literal/resources/reference/types/send_request.py new file mode 100644 index 00000000000..3f48f15773e --- /dev/null +++ b/seed/pydantic-v2/literal/resources/reference/types/send_request.py @@ -0,0 +1,19 @@ +from pydantic import BaseModel +from typing import Optional +from resources.reference.types.container_object import ContainerObject +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class SendRequest(BaseModel): + prompt: str + query: str + stream: bool + context: str + maybe_context: Optional[str] + container_object: ContainerObject + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/literal/resources/reference/types/some_literal.py b/seed/pydantic-v2/literal/resources/reference/types/some_literal.py new file mode 100644 index 00000000000..6b00c55e973 --- /dev/null +++ b/seed/pydantic-v2/literal/resources/reference/types/some_literal.py @@ -0,0 +1,19 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class SomeLiteral(RootModel[str]): + root: str + + def get_as_string() -> UUID: + return self.root + + @staticmethod + def from_string(value: str) -> SomeLiteral: + SomeLiteral(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/literal/snippet-templates.json b/seed/pydantic-v2/literal/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/literal/snippet.json b/seed/pydantic-v2/literal/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/literal/types/send_response.py b/seed/pydantic-v2/literal/types/send_response.py new file mode 100644 index 00000000000..124a79064de --- /dev/null +++ b/seed/pydantic-v2/literal/types/send_response.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class SendResponse(BaseModel): + message: str + status: int + success: bool + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/mixed-case/.mock/definition/api.yml b/seed/pydantic-v2/mixed-case/.mock/definition/api.yml new file mode 100644 index 00000000000..cf9d2078f7f --- /dev/null +++ b/seed/pydantic-v2/mixed-case/.mock/definition/api.yml @@ -0,0 +1 @@ +name: mixed-case \ No newline at end of file diff --git a/seed/pydantic-v2/mixed-case/.mock/definition/service.yml b/seed/pydantic-v2/mixed-case/.mock/definition/service.yml new file mode 100644 index 00000000000..7a38e853c35 --- /dev/null +++ b/seed/pydantic-v2/mixed-case/.mock/definition/service.yml @@ -0,0 +1,118 @@ +types: + Organization: + properties: + name: string + examples: + - name: One + value: + name: orgName + + User: + properties: + userName: string + metadata_tags: list + EXTRA_PROPERTIES: map + examples: + - name: One + value: + userName: username + metadata_tags: + - tag1 + - tag2 + EXTRA_PROPERTIES: + foo: bar + baz: qux + + NestedUser: + properties: + Name: string + NestedUser: User + examples: + - name: One + value: + Name: username + NestedUser: + userName: nestedUsername + metadata_tags: + - tag1 + - tag2 + EXTRA_PROPERTIES: + foo: bar + baz: qux + + ResourceStatus: + enum: + - ACTIVE + - INACTIVE + + Resource: + discriminant: + value: resource_type + name: resourceType + base-properties: + status: ResourceStatus + union: + user: User + Organization: Organization + examples: + - value: + status: ACTIVE + resource_type: user + userName: username + metadata_tags: + - tag1 + - tag2 + EXTRA_PROPERTIES: + foo: bar + baz: qux + +service: + base-path: /resource + auth: false + endpoints: + getResource: + path: "/{ResourceID}" + method: GET + path-parameters: + ResourceID: string + response: Resource + examples: + - path-parameters: + ResourceID: "rsc-xyz" + response: + body: + status: ACTIVE + resource_type: user + userName: username + metadata_tags: + - tag1 + - tag2 + EXTRA_PROPERTIES: + foo: bar + baz: qux + + listResources: + path: "" + method: GET + request: + name: ListResourcesRequest + query-parameters: + page_limit: integer + beforeDate: date + response: list + examples: + - name: One + query-parameters: + page_limit: 10 + beforeDate: "2023-01-01" + response: + body: + - resource_type: user + status: ACTIVE + userName: username + metadata_tags: + - tag1 + - tag2 + EXTRA_PROPERTIES: + foo: bar + baz: qux diff --git a/seed/pydantic-v2/mixed-case/.mock/fern.config.json b/seed/pydantic-v2/mixed-case/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/mixed-case/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/mixed-case/.mock/generators.yml b/seed/pydantic-v2/mixed-case/.mock/generators.yml new file mode 100644 index 00000000000..9e26dfeeb6e --- /dev/null +++ b/seed/pydantic-v2/mixed-case/.mock/generators.yml @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/seed/pydantic-v2/mixed-case/resources/service/types/nested_user.py b/seed/pydantic-v2/mixed-case/resources/service/types/nested_user.py new file mode 100644 index 00000000000..7b9af203334 --- /dev/null +++ b/seed/pydantic-v2/mixed-case/resources/service/types/nested_user.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from resources.service.types.user import User +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class NestedUser(BaseModel): + name: str + nested_user: User + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/mixed-case/resources/service/types/organization.py b/seed/pydantic-v2/mixed-case/resources/service/types/organization.py new file mode 100644 index 00000000000..6fe8b18b556 --- /dev/null +++ b/seed/pydantic-v2/mixed-case/resources/service/types/organization.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Organization(BaseModel): + name: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/mixed-case/resources/service/types/user.py b/seed/pydantic-v2/mixed-case/resources/service/types/user.py new file mode 100644 index 00000000000..6cf7bfa8ea7 --- /dev/null +++ b/seed/pydantic-v2/mixed-case/resources/service/types/user.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel +from typing import List, Dict +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class User(BaseModel): + user_name: str + metadata_tags: List[str] + extra_properties: Dict[str, str] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/mixed-case/snippet-templates.json b/seed/pydantic-v2/mixed-case/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/mixed-case/snippet.json b/seed/pydantic-v2/mixed-case/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/mixed-file-directory/.mock/definition/__package__.yml b/seed/pydantic-v2/mixed-file-directory/.mock/definition/__package__.yml new file mode 100644 index 00000000000..c4224b55354 --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/.mock/definition/__package__.yml @@ -0,0 +1,2 @@ +types: + Id: string diff --git a/seed/pydantic-v2/mixed-file-directory/.mock/definition/api.yml b/seed/pydantic-v2/mixed-file-directory/.mock/definition/api.yml new file mode 100644 index 00000000000..7d680d624f8 --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/.mock/definition/api.yml @@ -0,0 +1 @@ +name: mixed-file-directory diff --git a/seed/pydantic-v2/mixed-file-directory/.mock/definition/organization.yml b/seed/pydantic-v2/mixed-file-directory/.mock/definition/organization.yml new file mode 100644 index 00000000000..6b1021dfd9c --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/.mock/definition/organization.yml @@ -0,0 +1,26 @@ +imports: + root: __package__.yml + user: user.yml + +types: + Organization: + properties: + id: root.Id + name: string + users: list + + CreateOrganizationRequest: + properties: + name: string + +service: + auth: false + base-path: /organizations + endpoints: + create: + path: / + method: POST + auth: false + docs: Create a new organization. + request: CreateOrganizationRequest + response: Organization diff --git a/seed/pydantic-v2/mixed-file-directory/.mock/definition/user.yml b/seed/pydantic-v2/mixed-file-directory/.mock/definition/user.yml new file mode 100644 index 00000000000..f6d372b45f4 --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/.mock/definition/user.yml @@ -0,0 +1,26 @@ +imports: + root: __package__.yml + +types: + User: + properties: + id: root.Id + name: string + age: integer + +service: + auth: false + base-path: /users + endpoints: + list: + path: / + method: GET + auth: false + docs: List all users. + request: + name: ListUsersRequest + query-parameters: + limit: + type: optional + docs: The maximum number of results to return. + response: list diff --git a/seed/pydantic-v2/mixed-file-directory/.mock/definition/user/events.yml b/seed/pydantic-v2/mixed-file-directory/.mock/definition/user/events.yml new file mode 100644 index 00000000000..e0d993ff09b --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/.mock/definition/user/events.yml @@ -0,0 +1,26 @@ +imports: + root: ../__package__.yml + user: ../user.yml + +types: + Event: + properties: + id: root.Id + name: string + +service: + auth: false + base-path: /users/events + endpoints: + listEvents: + path: / + method: GET + auth: false + docs: List all user events. + request: + name: ListUserEventsRequest + query-parameters: + limit: + type: optional + docs: The maximum number of results to return. + response: list diff --git a/seed/pydantic-v2/mixed-file-directory/.mock/definition/user/events/metadata.yml b/seed/pydantic-v2/mixed-file-directory/.mock/definition/user/events/metadata.yml new file mode 100644 index 00000000000..f38b5afcb12 --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/.mock/definition/user/events/metadata.yml @@ -0,0 +1,23 @@ +imports: + root: ../../__package__.yml + +types: + Metadata: + properties: + id: root.Id + value: unknown + +service: + auth: false + base-path: /users/events/metadata + endpoints: + getMetadata: + path: / + method: GET + auth: false + docs: Get event metadata. + request: + name: GetEventMetadataRequest + query-parameters: + id: root.Id + response: Metadata diff --git a/seed/pydantic-v2/mixed-file-directory/.mock/fern.config.json b/seed/pydantic-v2/mixed-file-directory/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/mixed-file-directory/.mock/generators.yml b/seed/pydantic-v2/mixed-file-directory/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/mixed-file-directory/resources/organization/types/create_organization_request.py b/seed/pydantic-v2/mixed-file-directory/resources/organization/types/create_organization_request.py new file mode 100644 index 00000000000..30ef262b17a --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/resources/organization/types/create_organization_request.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class CreateOrganizationRequest(BaseModel): + name: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/mixed-file-directory/resources/organization/types/organization.py b/seed/pydantic-v2/mixed-file-directory/resources/organization/types/organization.py new file mode 100644 index 00000000000..1d4ef6582a6 --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/resources/organization/types/organization.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel +from typing import List +from resources.user.types.user import User +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Organization(BaseModel): + id: str + name: str + users: List[User] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/mixed-file-directory/resources/user/resources/events/resources/metadata/types/metadata.py b/seed/pydantic-v2/mixed-file-directory/resources/user/resources/events/resources/metadata/types/metadata.py new file mode 100644 index 00000000000..ca0f5a333de --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/resources/user/resources/events/resources/metadata/types/metadata.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Any +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Metadata(BaseModel): + id: str + value: Any + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/mixed-file-directory/resources/user/resources/events/types/event.py b/seed/pydantic-v2/mixed-file-directory/resources/user/resources/events/types/event.py new file mode 100644 index 00000000000..9fb77756566 --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/resources/user/resources/events/types/event.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Event(BaseModel): + id: str + name: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/mixed-file-directory/resources/user/types/user.py b/seed/pydantic-v2/mixed-file-directory/resources/user/types/user.py new file mode 100644 index 00000000000..97d63c4723b --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/resources/user/types/user.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class User(BaseModel): + id: str + name: str + age: int + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/mixed-file-directory/snippet-templates.json b/seed/pydantic-v2/mixed-file-directory/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/mixed-file-directory/snippet.json b/seed/pydantic-v2/mixed-file-directory/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/mixed-file-directory/types/id.py b/seed/pydantic-v2/mixed-file-directory/types/id.py new file mode 100644 index 00000000000..3f8f15db9d4 --- /dev/null +++ b/seed/pydantic-v2/mixed-file-directory/types/id.py @@ -0,0 +1,19 @@ +from pydantic import RootModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Id(RootModel[str]): + root: str + + def get_as_str() -> UUID: + return self.root + + @staticmethod + def from_str(value: str) -> Id: + Id(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/multi-line-docs/.mock/definition/__package__.yml b/seed/pydantic-v2/multi-line-docs/.mock/definition/__package__.yml new file mode 100644 index 00000000000..6ad9eb4833f --- /dev/null +++ b/seed/pydantic-v2/multi-line-docs/.mock/definition/__package__.yml @@ -0,0 +1,19 @@ +types: + Operand: + docs: | + Tests enum name and value can be + different. + enum: + - value: ">" + name: GREATER_THAN + - value: "=" + name: EQUAL_TO + - value: "less_than" + docs: | + The name and value should be similar + are similar for less than. + examples: + - name: GreaterThan + value: ">" + - name: LessThan + value: "less_than" diff --git a/seed/pydantic-v2/multi-line-docs/.mock/definition/api.yml b/seed/pydantic-v2/multi-line-docs/.mock/definition/api.yml new file mode 100644 index 00000000000..31a2076dc87 --- /dev/null +++ b/seed/pydantic-v2/multi-line-docs/.mock/definition/api.yml @@ -0,0 +1 @@ +name: multi-line-docs diff --git a/seed/pydantic-v2/multi-line-docs/.mock/definition/user.yml b/seed/pydantic-v2/multi-line-docs/.mock/definition/user.yml new file mode 100644 index 00000000000..a7ffb021a43 --- /dev/null +++ b/seed/pydantic-v2/multi-line-docs/.mock/definition/user.yml @@ -0,0 +1,61 @@ +imports: + root: __package__.yml + +types: + User: + docs: | + A user object. This type is used throughout the following APIs: + - createUser + - getUser + properties: + id: string + name: + type: string + docs: | + The user's name. This name is unique to each user. A few examples are included below: + - Alice + - Bob + - Charlie + age: + type: optional + docs: | + The user's age. + +service: + auth: false + base-path: "" + endpoints: + getUser: + docs: | + Retrieve a user. + This endpoint is used to retrieve a user. + path: /users/{userId} + method: GET + path-parameters: + userId: + type: string + docs: | + The ID of the user to retrieve. + This ID is unique to each user. + + createUser: + docs: | + Create a new user. + This endpoint is used to create a new user. + path: /users + method: POST + request: + name: CreateUserRequest + body: + properties: + name: + type: string + docs: | + The name of the user to create. + This name is unique to each user. + age: + type: optional + docs: | + The age of the user. + This propery is not required. + response: User \ No newline at end of file diff --git a/seed/pydantic-v2/multi-line-docs/.mock/fern.config.json b/seed/pydantic-v2/multi-line-docs/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/multi-line-docs/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/multi-line-docs/.mock/generators.yml b/seed/pydantic-v2/multi-line-docs/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/multi-line-docs/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/multi-line-docs/resources/user/types/user.py b/seed/pydantic-v2/multi-line-docs/resources/user/types/user.py new file mode 100644 index 00000000000..5b01839d2ba --- /dev/null +++ b/seed/pydantic-v2/multi-line-docs/resources/user/types/user.py @@ -0,0 +1,27 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime +class User(BaseModel): +"""A user object. This type is used throughout the following APIs: + +- createUser +- getUser""" + id: str + name: str + """ + The user's name. This name is unique to each user. A few examples are included below: + + - Alice + - Bob + - Charlie + """ + age: Optional[int] = None + """ + The user's age. + """ + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/multi-line-docs/snippet-templates.json b/seed/pydantic-v2/multi-line-docs/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/multi-line-docs/snippet.json b/seed/pydantic-v2/multi-line-docs/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/multi-url-environment-no-default/.mock/definition/api.yml b/seed/pydantic-v2/multi-url-environment-no-default/.mock/definition/api.yml new file mode 100644 index 00000000000..118b0a1177e --- /dev/null +++ b/seed/pydantic-v2/multi-url-environment-no-default/.mock/definition/api.yml @@ -0,0 +1,14 @@ +name: multi-url-environment-no-default +auth: bearer +environments: + Production: + urls: + ec2: https://ec2.aws.com + s3: https://s3.aws.com + Staging: + urls: + ec2: https://staging.ec2.aws.com + s3: https://staging.s3.aws.com +default-environment: null +error-discrimination: + strategy: status-code diff --git a/seed/pydantic-v2/multi-url-environment-no-default/.mock/definition/ec2.yml b/seed/pydantic-v2/multi-url-environment-no-default/.mock/definition/ec2.yml new file mode 100644 index 00000000000..a3acc4216ff --- /dev/null +++ b/seed/pydantic-v2/multi-url-environment-no-default/.mock/definition/ec2.yml @@ -0,0 +1,16 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +service: + auth: true + url: ec2 + base-path: /ec2 + endpoints: + bootInstance: + auth: true + path: /boot + method: POST + request: + name: BootInstanceRequest + body: + properties: + size: string diff --git a/seed/pydantic-v2/multi-url-environment-no-default/.mock/definition/s3.yml b/seed/pydantic-v2/multi-url-environment-no-default/.mock/definition/s3.yml new file mode 100644 index 00000000000..ca741b783f5 --- /dev/null +++ b/seed/pydantic-v2/multi-url-environment-no-default/.mock/definition/s3.yml @@ -0,0 +1,17 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +service: + auth: true + url: s3 + base-path: /s3 + endpoints: + getPresignedUrl: + auth: true + path: /presigned-url + method: POST + request: + name: GetPresignedUrlRequest + body: + properties: + s3Key: string + response: string diff --git a/seed/pydantic-v2/multi-url-environment-no-default/.mock/fern.config.json b/seed/pydantic-v2/multi-url-environment-no-default/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/multi-url-environment-no-default/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/multi-url-environment-no-default/.mock/generators.yml b/seed/pydantic-v2/multi-url-environment-no-default/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/multi-url-environment-no-default/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/multi-url-environment-no-default/snippet-templates.json b/seed/pydantic-v2/multi-url-environment-no-default/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/multi-url-environment-no-default/snippet.json b/seed/pydantic-v2/multi-url-environment-no-default/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/multi-url-environment/.mock/definition/api.yml b/seed/pydantic-v2/multi-url-environment/.mock/definition/api.yml new file mode 100644 index 00000000000..f362d991927 --- /dev/null +++ b/seed/pydantic-v2/multi-url-environment/.mock/definition/api.yml @@ -0,0 +1,14 @@ +name: multi-url-environment +auth: bearer +environments: + Production: + urls: + ec2: https://ec2.aws.com + s3: https://s3.aws.com + Staging: + urls: + ec2: https://staging.ec2.aws.com + s3: https://staging.s3.aws.com +default-environment: Production +error-discrimination: + strategy: status-code diff --git a/seed/pydantic-v2/multi-url-environment/.mock/definition/ec2.yml b/seed/pydantic-v2/multi-url-environment/.mock/definition/ec2.yml new file mode 100644 index 00000000000..a3acc4216ff --- /dev/null +++ b/seed/pydantic-v2/multi-url-environment/.mock/definition/ec2.yml @@ -0,0 +1,16 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +service: + auth: true + url: ec2 + base-path: /ec2 + endpoints: + bootInstance: + auth: true + path: /boot + method: POST + request: + name: BootInstanceRequest + body: + properties: + size: string diff --git a/seed/pydantic-v2/multi-url-environment/.mock/definition/s3.yml b/seed/pydantic-v2/multi-url-environment/.mock/definition/s3.yml new file mode 100644 index 00000000000..ca741b783f5 --- /dev/null +++ b/seed/pydantic-v2/multi-url-environment/.mock/definition/s3.yml @@ -0,0 +1,17 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +service: + auth: true + url: s3 + base-path: /s3 + endpoints: + getPresignedUrl: + auth: true + path: /presigned-url + method: POST + request: + name: GetPresignedUrlRequest + body: + properties: + s3Key: string + response: string diff --git a/seed/pydantic-v2/multi-url-environment/.mock/fern.config.json b/seed/pydantic-v2/multi-url-environment/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/multi-url-environment/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/multi-url-environment/.mock/generators.yml b/seed/pydantic-v2/multi-url-environment/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/multi-url-environment/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/multi-url-environment/snippet-templates.json b/seed/pydantic-v2/multi-url-environment/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/multi-url-environment/snippet.json b/seed/pydantic-v2/multi-url-environment/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/no-environment/.mock/definition/api.yml b/seed/pydantic-v2/no-environment/.mock/definition/api.yml new file mode 100644 index 00000000000..d47556ced41 --- /dev/null +++ b/seed/pydantic-v2/no-environment/.mock/definition/api.yml @@ -0,0 +1,4 @@ +name: no-environment +auth: bearer +error-discrimination: + strategy: status-code diff --git a/seed/pydantic-v2/no-environment/.mock/definition/dummy.yml b/seed/pydantic-v2/no-environment/.mock/definition/dummy.yml new file mode 100644 index 00000000000..e767095a9b0 --- /dev/null +++ b/seed/pydantic-v2/no-environment/.mock/definition/dummy.yml @@ -0,0 +1,11 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +service: + auth: true + base-path: "" + endpoints: + getDummy: + auth: true + path: /dummy + method: GET + response: string diff --git a/seed/pydantic-v2/no-environment/.mock/fern.config.json b/seed/pydantic-v2/no-environment/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/no-environment/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/no-environment/.mock/generators.yml b/seed/pydantic-v2/no-environment/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/no-environment/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/no-environment/snippet-templates.json b/seed/pydantic-v2/no-environment/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/no-environment/snippet.json b/seed/pydantic-v2/no-environment/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/oauth-client-credentials-default/.mock/definition/api.yml b/seed/pydantic-v2/oauth-client-credentials-default/.mock/definition/api.yml new file mode 100644 index 00000000000..e94a5d4e99d --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-default/.mock/definition/api.yml @@ -0,0 +1,11 @@ +name: oauth-client-credentials-default +imports: + auth: auth.yml + +auth: OAuthScheme +auth-schemes: + OAuthScheme: + scheme: oauth + type: client-credentials + get-token: + endpoint: auth.getToken \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials-default/.mock/definition/auth.yml b/seed/pydantic-v2/oauth-client-credentials-default/.mock/definition/auth.yml new file mode 100644 index 00000000000..ca7f4017566 --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-default/.mock/definition/auth.yml @@ -0,0 +1,23 @@ +types: + TokenResponse: + docs: | + An OAuth token response. + properties: + access_token: string + expires_in: integer + +service: + auth: false + base-path: / + endpoints: + getToken: + path: /token + method: POST + request: + name: GetTokenRequest + body: + properties: + client_id: string + client_secret: string + grant_type: literal<"client_credentials"> + response: TokenResponse \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials-default/.mock/fern.config.json b/seed/pydantic-v2/oauth-client-credentials-default/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-default/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials-default/.mock/generators.yml b/seed/pydantic-v2/oauth-client-credentials-default/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-default/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/oauth-client-credentials-default/resources/auth/types/token_response.py b/seed/pydantic-v2/oauth-client-credentials-default/resources/auth/types/token_response.py new file mode 100644 index 00000000000..375c3273b8d --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-default/resources/auth/types/token_response.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime +class TokenResponse(BaseModel): +"""An OAuth token response.""" + access_token: str + expires_in: int + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/oauth-client-credentials-default/snippet-templates.json b/seed/pydantic-v2/oauth-client-credentials-default/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/oauth-client-credentials-default/snippet.json b/seed/pydantic-v2/oauth-client-credentials-default/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/definition/api.yml b/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/definition/api.yml new file mode 100644 index 00000000000..3869123994b --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/definition/api.yml @@ -0,0 +1,16 @@ +name: oauth-client-credentials-environment-variables +imports: + auth: auth.yml + +auth: OAuthScheme +auth-schemes: + OAuthScheme: + scheme: oauth + type: client-credentials + client-id-env: CLIENT_ID + client-secret-env: CLIENT_SECRET + get-token: + endpoint: auth.getTokenWithClientCredentials + response-properties: + access-token: $response.access_token + expires-in: $response.expires_in \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/definition/auth.yml b/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/definition/auth.yml new file mode 100644 index 00000000000..b0dc81c642a --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/definition/auth.yml @@ -0,0 +1,41 @@ +types: + TokenResponse: + docs: | + An OAuth token response. + properties: + access_token: string + expires_in: integer + refresh_token: optional + +service: + auth: false + base-path: / + endpoints: + getTokenWithClientCredentials: + path: /token + method: POST + request: + name: GetTokenRequest + body: + properties: + client_id: string + client_secret: string + audience: literal<"https://api.example.com"> + grant_type: literal<"client_credentials"> + scope: optional + response: TokenResponse + + refreshToken: + path: /token + method: POST + request: + name: RefreshTokenRequest + body: + properties: + client_id: string + client_secret: string + refresh_token: string + audience: literal<"https://api.example.com"> + grant_type: literal<"refresh_token"> + scope: optional + response: TokenResponse \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/fern.config.json b/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/generators.yml b/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-environment-variables/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/oauth-client-credentials-environment-variables/resources/auth/types/token_response.py b/seed/pydantic-v2/oauth-client-credentials-environment-variables/resources/auth/types/token_response.py new file mode 100644 index 00000000000..2ed020441af --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-environment-variables/resources/auth/types/token_response.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime +class TokenResponse(BaseModel): +"""An OAuth token response.""" + access_token: str + expires_in: int + refresh_token: Optional[str] = None + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/oauth-client-credentials-environment-variables/snippet-templates.json b/seed/pydantic-v2/oauth-client-credentials-environment-variables/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/oauth-client-credentials-environment-variables/snippet.json b/seed/pydantic-v2/oauth-client-credentials-environment-variables/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/definition/api.yml b/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/definition/api.yml new file mode 100644 index 00000000000..6ce1df51a05 --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/definition/api.yml @@ -0,0 +1,14 @@ +name: oauth-client-credentials +imports: + auth: auth/__package__.yml + +auth: OAuthScheme +auth-schemes: + OAuthScheme: + scheme: oauth + type: client-credentials + get-token: + endpoint: auth.getToken + response-properties: + access-token: $response.access_token + expires-in: $response.expires_in \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/definition/auth/__package__.yml b/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/definition/auth/__package__.yml new file mode 100644 index 00000000000..a1d4f02e92e --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/definition/auth/__package__.yml @@ -0,0 +1,26 @@ +types: + TokenResponse: + docs: | + An OAuth token response. + properties: + access_token: string + expires_in: integer + refresh_token: optional + +service: + auth: false + base-path: / + endpoints: + getToken: + path: /token + method: POST + request: + name: GetTokenRequest + body: + properties: + client_id: string + client_secret: string + audience: literal<"https://api.example.com"> + grant_type: literal<"client_credentials"> + scope: optional + response: TokenResponse \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/fern.config.json b/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/generators.yml b/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-nested-root/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/oauth-client-credentials-nested-root/resources/auth/types/token_response.py b/seed/pydantic-v2/oauth-client-credentials-nested-root/resources/auth/types/token_response.py new file mode 100644 index 00000000000..2ed020441af --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials-nested-root/resources/auth/types/token_response.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime +class TokenResponse(BaseModel): +"""An OAuth token response.""" + access_token: str + expires_in: int + refresh_token: Optional[str] = None + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/oauth-client-credentials-nested-root/snippet-templates.json b/seed/pydantic-v2/oauth-client-credentials-nested-root/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/oauth-client-credentials-nested-root/snippet.json b/seed/pydantic-v2/oauth-client-credentials-nested-root/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/oauth-client-credentials/.mock/definition/api.yml b/seed/pydantic-v2/oauth-client-credentials/.mock/definition/api.yml new file mode 100644 index 00000000000..3ca293f63ed --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials/.mock/definition/api.yml @@ -0,0 +1,14 @@ +name: oauth-client-credentials +imports: + auth: auth.yml + +auth: OAuthScheme +auth-schemes: + OAuthScheme: + scheme: oauth + type: client-credentials + get-token: + endpoint: auth.getTokenWithClientCredentials + response-properties: + access-token: $response.access_token + expires-in: $response.expires_in \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials/.mock/definition/auth.yml b/seed/pydantic-v2/oauth-client-credentials/.mock/definition/auth.yml new file mode 100644 index 00000000000..e7887dddb67 --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials/.mock/definition/auth.yml @@ -0,0 +1,41 @@ +types: + TokenResponse: + docs: | + An OAuth token response. + properties: + access_token: string + expires_in: integer + refresh_token: optional + +service: + auth: false + base-path: / + endpoints: + getTokenWithClientCredentials: + path: /token + method: POST + request: + name: GetTokenRequest + body: + properties: + client_id: string + client_secret: string + audience: literal<"https://api.example.com"> + grant_type: literal<"client_credentials"> + scope: optional + response: TokenResponse + + refreshToken: + path: /token + method: POST + request: + name: RefreshTokenRequest + body: + properties: + client_id: string + client_secret: string + refresh_token: string + audience: literal<"https://api.example.com"> + grant_type: literal<"refresh_token"> + scope: optional + response: TokenResponse \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials/.mock/fern.config.json b/seed/pydantic-v2/oauth-client-credentials/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/oauth-client-credentials/.mock/generators.yml b/seed/pydantic-v2/oauth-client-credentials/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/oauth-client-credentials/resources/auth/types/token_response.py b/seed/pydantic-v2/oauth-client-credentials/resources/auth/types/token_response.py new file mode 100644 index 00000000000..2ed020441af --- /dev/null +++ b/seed/pydantic-v2/oauth-client-credentials/resources/auth/types/token_response.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime +class TokenResponse(BaseModel): +"""An OAuth token response.""" + access_token: str + expires_in: int + refresh_token: Optional[str] = None + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/oauth-client-credentials/snippet-templates.json b/seed/pydantic-v2/oauth-client-credentials/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/oauth-client-credentials/snippet.json b/seed/pydantic-v2/oauth-client-credentials/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/object/.mock/definition/__package__.yml b/seed/pydantic-v2/object/.mock/definition/__package__.yml new file mode 100644 index 00000000000..8dee80b552b --- /dev/null +++ b/seed/pydantic-v2/object/.mock/definition/__package__.yml @@ -0,0 +1,79 @@ +types: + Type: + docs: | + Exercises all of the built-in types. + properties: + one: integer + two: double + three: string + four: boolean + five: long + six: datetime + seven: date + eight: uuid + nine: base64 + ten: list + eleven: set + twelve: map + thirteen: optional + fourteen: unknown + fifteen: list> + sixteen: list> + seventeen: list> + eighteen: literal<"eighteen"> + nineteen: Name + twenty: uint + twentyone: uint64 + twentytwo: float + twentythree: bigint + examples: + - name: One + value: + one: 1 + two: 2 + three: three + four: true + five: 5 + six: 1994-01-01T01:01:01Z + seven: 1994-01-01 + eight: 7f71f677-e138-4a5c-bb01-e4453a19bfef + nine: TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu + ten: + - 10 + - 10 + eleven: + - 11 + twelve: + invalid: false + exists: true + thirteen: 13 + fourteen: {} + fifteen: + - - 15 + - 15 + - - 15 + - 15 + sixteen: + - foo: 16 + bar: 16 + seventeen: + - 244c6643-f99d-4bfc-b20d-a6518f3a4cf4 + - 07791987-dec3-43b5-8dc4-250ab5dc0478 + eighteen: eighteen + nineteen: + id: name-129fsdj9 + value: nineteen + twenty: 20 + twentyone: 21 + twentytwo: 22.22 + twentythree: "23" + + Name: + properties: + id: string + value: string + examples: + - name: One + value: + id: name-sdfg8ajk + value: name diff --git a/seed/pydantic-v2/object/.mock/definition/api.yml b/seed/pydantic-v2/object/.mock/definition/api.yml new file mode 100644 index 00000000000..a82930c145b --- /dev/null +++ b/seed/pydantic-v2/object/.mock/definition/api.yml @@ -0,0 +1 @@ +name: object diff --git a/seed/pydantic-v2/object/.mock/fern.config.json b/seed/pydantic-v2/object/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/object/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/object/.mock/generators.yml b/seed/pydantic-v2/object/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/object/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/object/snippet-templates.json b/seed/pydantic-v2/object/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/object/snippet.json b/seed/pydantic-v2/object/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/object/types/name.py b/seed/pydantic-v2/object/types/name.py new file mode 100644 index 00000000000..658a908c805 --- /dev/null +++ b/seed/pydantic-v2/object/types/name.py @@ -0,0 +1,11 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime +class Name(BaseModel): + id: str + value: str + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/object/types/type.py b/seed/pydantic-v2/object/types/type.py new file mode 100644 index 00000000000..fff32f433eb --- /dev/null +++ b/seed/pydantic-v2/object/types/type.py @@ -0,0 +1,37 @@ +from pydantic import BaseModel +from datetime import datetime +from uuid import UUID +from typing import List, Set, Dict, Optional, Any +from .types.name import Name +from dt import datetime +from core.datetime_utils import serialize_datetime +class Type(BaseModel): +"""Exercises all of the built-in types.""" + one: int + two: float + three: str + four: bool + five: int + six: datetime + seven: str + eight: UUID + nine: bytes + ten: List[int] + eleven: Set[float] + twelve: Dict[str, bool] + thirteen: Optional[int] = None + fourteen: Any + fifteen: List[List[int]] + sixteen: List[Dict[str, int]] + seventeen: List[Optional[UUID]] + eighteen: str + nineteen: Name + twenty: int + twentyone: int + twentytwo: float + twentythree: str + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} + diff --git a/seed/pydantic-v2/objects-with-imports/.mock/definition/__package__.yml b/seed/pydantic-v2/objects-with-imports/.mock/definition/__package__.yml new file mode 100644 index 00000000000..f3bdf68f26a --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/.mock/definition/__package__.yml @@ -0,0 +1,37 @@ +imports: + metadata: commons/metadata.yml +types: + Node: + properties: + id: string + label: optional + metadata: optional + examples: + - name: Left + value: + id: node-8dvgfja2 + label: left + metadata: + id: metadata-kjasf923 + data: + foo: bar + baz: qux + - name: Right + value: + id: node-cwda9fi2x + label: right + metadata: + id: metadata-lkasdfv9j + data: + one: two + three: four + + Tree: + properties: + nodes: optional> + examples: + - name: Root + value: + nodes: + - $Node.Left + - $Node.Right diff --git a/seed/pydantic-v2/objects-with-imports/.mock/definition/api.yml b/seed/pydantic-v2/objects-with-imports/.mock/definition/api.yml new file mode 100644 index 00000000000..de1eb78549d --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/.mock/definition/api.yml @@ -0,0 +1 @@ +name: objects-with-imports diff --git a/seed/pydantic-v2/objects-with-imports/.mock/definition/commons/metadata.yml b/seed/pydantic-v2/objects-with-imports/.mock/definition/commons/metadata.yml new file mode 100644 index 00000000000..5672f92f415 --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/.mock/definition/commons/metadata.yml @@ -0,0 +1,12 @@ +types: + Metadata: + properties: + id: string + data: optional> + examples: + - name: One + value: + id: metadata-js8dg24b + data: + foo: bar + baz: qux diff --git a/seed/pydantic-v2/objects-with-imports/.mock/definition/file.yml b/seed/pydantic-v2/objects-with-imports/.mock/definition/file.yml new file mode 100644 index 00000000000..187b75e3af0 --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/.mock/definition/file.yml @@ -0,0 +1,29 @@ +types: + File: + properties: + name: string + contents: string + info: FileInfo + examples: + - name: One + value: + name: file.txt + contents: ... + info: REGULAR + - name: Two + value: + name: another_file.txt + contents: ... + info: REGULAR + + FileInfo: + enum: + - value: REGULAR + docs: A regular file (e.g. foo.txt). + - value: DIRECTORY + docs: A directory (e.g. foo/). + examples: + - name: Regular + value: REGULAR + - name: Directory + value: DIRECTORY diff --git a/seed/pydantic-v2/objects-with-imports/.mock/definition/file/directory.yml b/seed/pydantic-v2/objects-with-imports/.mock/definition/file/directory.yml new file mode 100644 index 00000000000..4902de7db69 --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/.mock/definition/file/directory.yml @@ -0,0 +1,18 @@ +imports: + file: ../file.yml +types: + Directory: + properties: + name: string + files: optional> + directories: optional> + examples: + - name: One + value: + name: root + files: + - $file.File.One + directories: + - name: tmp + files: + - $file.File.Two diff --git a/seed/pydantic-v2/objects-with-imports/.mock/fern.config.json b/seed/pydantic-v2/objects-with-imports/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/objects-with-imports/.mock/generators.yml b/seed/pydantic-v2/objects-with-imports/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/objects-with-imports/resources/commons/resources/metadata/types/metadata.py b/seed/pydantic-v2/objects-with-imports/resources/commons/resources/metadata/types/metadata.py new file mode 100644 index 00000000000..5588b840935 --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/resources/commons/resources/metadata/types/metadata.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional, Dict +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Metadata(BaseModel): + id: str + data: Optional[Dict[str, str]] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/objects-with-imports/resources/file/resources/directory/types/directory.py b/seed/pydantic-v2/objects-with-imports/resources/file/resources/directory/types/directory.py new file mode 100644 index 00000000000..4e5a1c31024 --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/resources/file/resources/directory/types/directory.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel +from typing import Optional, List +from resources.file.types.file import File +from resources.file.resources.directory.types.directory import Directory +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Directory(BaseModel): + name: str + files: Optional[List[File]] = None + directories: Optional[List[Directory]] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/objects-with-imports/resources/file/types/file.py b/seed/pydantic-v2/objects-with-imports/resources/file/types/file.py new file mode 100644 index 00000000000..bd6b8be92f6 --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/resources/file/types/file.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel +from resources.file.types.file_info import FileInfo +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class File(BaseModel): + name: str + contents: str + info: FileInfo + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/objects-with-imports/snippet-templates.json b/seed/pydantic-v2/objects-with-imports/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/objects-with-imports/snippet.json b/seed/pydantic-v2/objects-with-imports/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/objects-with-imports/types/node.py b/seed/pydantic-v2/objects-with-imports/types/node.py new file mode 100644 index 00000000000..095367a74be --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/types/node.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel +from typing import Optional +from resources.commons.resources.metadata.types.metadata import Metadata +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Node(BaseModel): + id: str + label: Optional[str] = None + metadata: Optional[Metadata] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/objects-with-imports/types/tree.py b/seed/pydantic-v2/objects-with-imports/types/tree.py new file mode 100644 index 00000000000..76fc5aaece0 --- /dev/null +++ b/seed/pydantic-v2/objects-with-imports/types/tree.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional, List +from .types.node import Node +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Tree(BaseModel): + nodes: Optional[List[Node]] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/optional/.mock/definition/api.yml b/seed/pydantic-v2/optional/.mock/definition/api.yml new file mode 100644 index 00000000000..de1eb78549d --- /dev/null +++ b/seed/pydantic-v2/optional/.mock/definition/api.yml @@ -0,0 +1 @@ +name: objects-with-imports diff --git a/seed/pydantic-v2/optional/.mock/definition/optional.yml b/seed/pydantic-v2/optional/.mock/definition/optional.yml new file mode 100644 index 00000000000..111f55357bb --- /dev/null +++ b/seed/pydantic-v2/optional/.mock/definition/optional.yml @@ -0,0 +1,11 @@ +service: + auth: false + base-path: "" + endpoints: + sendOptionalBody: + method: POST + path: /send-optional-body + request: optional> + response: + type: string + docs: Id of the created resource diff --git a/seed/pydantic-v2/optional/.mock/fern.config.json b/seed/pydantic-v2/optional/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/optional/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/optional/.mock/generators.yml b/seed/pydantic-v2/optional/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/optional/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/optional/snippet-templates.json b/seed/pydantic-v2/optional/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/optional/snippet.json b/seed/pydantic-v2/optional/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/package-yml/.mock/definition/__package__.yml b/seed/pydantic-v2/package-yml/.mock/definition/__package__.yml new file mode 100644 index 00000000000..f46211acabf --- /dev/null +++ b/seed/pydantic-v2/package-yml/.mock/definition/__package__.yml @@ -0,0 +1,23 @@ +service: + auth: false + base-path: / + endpoints: + echo: + method: POST + path: "" + request: EchoRequest + response: string + examples: + - path-parameters: + id: id-ksfd9c1 + request: + name: Hello world! + size: 20 + response: + body: Hello world! + +types: + EchoRequest: + properties: + name: string + size: integer \ No newline at end of file diff --git a/seed/pydantic-v2/package-yml/.mock/definition/api.yml b/seed/pydantic-v2/package-yml/.mock/definition/api.yml new file mode 100644 index 00000000000..eedda1ebe19 --- /dev/null +++ b/seed/pydantic-v2/package-yml/.mock/definition/api.yml @@ -0,0 +1,4 @@ +name: package-yml +base-path: /{id} +path-parameters: + id: string diff --git a/seed/pydantic-v2/package-yml/.mock/definition/service.yml b/seed/pydantic-v2/package-yml/.mock/definition/service.yml new file mode 100644 index 00000000000..3201fb14c66 --- /dev/null +++ b/seed/pydantic-v2/package-yml/.mock/definition/service.yml @@ -0,0 +1,13 @@ +service: + auth: false + base-path: / + endpoints: + nop: + method: GET + path: /{nestedId} + path-parameters: + nestedId: string + examples: + - path-parameters: + id: id-a2ijs82 + nestedId: id-219xca8 diff --git a/seed/pydantic-v2/package-yml/.mock/fern.config.json b/seed/pydantic-v2/package-yml/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/package-yml/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/package-yml/.mock/generators.yml b/seed/pydantic-v2/package-yml/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/package-yml/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/package-yml/snippet-templates.json b/seed/pydantic-v2/package-yml/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/package-yml/snippet.json b/seed/pydantic-v2/package-yml/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/package-yml/types/echo_request.py b/seed/pydantic-v2/package-yml/types/echo_request.py new file mode 100644 index 00000000000..38e1e89dd8e --- /dev/null +++ b/seed/pydantic-v2/package-yml/types/echo_request.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class EchoRequest(BaseModel): + name: str + size: int + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/.mock/definition/__package__.yml b/seed/pydantic-v2/pagination/.mock/definition/__package__.yml new file mode 100644 index 00000000000..54072fdf817 --- /dev/null +++ b/seed/pydantic-v2/pagination/.mock/definition/__package__.yml @@ -0,0 +1,9 @@ +types: + UsernameCursor: + properties: + cursor: UsernamePage + + UsernamePage: + properties: + after: optional + data: list \ No newline at end of file diff --git a/seed/pydantic-v2/pagination/.mock/definition/api.yml b/seed/pydantic-v2/pagination/.mock/definition/api.yml new file mode 100644 index 00000000000..9a8e8ee6796 --- /dev/null +++ b/seed/pydantic-v2/pagination/.mock/definition/api.yml @@ -0,0 +1,5 @@ +name: pagination +auth: bearer +pagination: + offset: $request.offset + results: $response.results \ No newline at end of file diff --git a/seed/pydantic-v2/pagination/.mock/definition/users.yml b/seed/pydantic-v2/pagination/.mock/definition/users.yml new file mode 100644 index 00000000000..ecde10ef707 --- /dev/null +++ b/seed/pydantic-v2/pagination/.mock/definition/users.yml @@ -0,0 +1,271 @@ +imports: + root: __package__.yml + +types: + Order: + enum: + - asc + - desc + + WithPage: + properties: + page: optional + + WithCursor: + properties: + cursor: optional + + UserListContainer: + properties: + users: list + + UserPage: + properties: + data: UserListContainer + next: optional + + UserOptionalListContainer: + properties: + users: optional> + + UserOptionalListPage: + properties: + data: UserOptionalListContainer + next: optional + + UsernameContainer: + properties: + results: list + + ListUsersExtendedResponse: + extends: + - UserPage + properties: + total_count: + type: integer + docs: The totall number of /users + + ListUsersExtendedOptionalListResponse: + extends: + - UserOptionalListPage + properties: + total_count: + type: integer + docs: The totall number of /users + + ListUsersPaginationResponse: + properties: + hasNextPage: optional + page: optional + total_count: + type: integer + docs: The totall number of /users + data: list + + Page: + properties: + page: + type: integer + docs: The current page + next: optional + per_page: integer + total_page: integer + + NextPage: + properties: + page: integer + starting_after: string + + User: + properties: + name: string + id: integer + +service: + auth: false + base-path: /users + endpoints: + listWithCursorPagination: + pagination: + cursor: $request.starting_after + next_cursor: $response.page.next.starting_after + results: $response.data + method: GET + path: "" + request: + name: ListUsersCursorPaginationRequest + query-parameters: + page: + type: optional + docs: Defaults to first page + per_page: + type: optional + docs: Defaults to per page + order: + type: optional + starting_after: + type: optional + docs: | + The cursor used for pagination in order to fetch + the next page of results. + response: ListUsersPaginationResponse + + listWithBodyCursorPagination: + pagination: + cursor: $request.pagination.cursor + next_cursor: $response.page.next.starting_after + results: $response.data + method: POST + path: "" + request: + name: ListUsersBodyCursorPaginationRequest + body: + properties: + pagination: + type: optional + docs: | + The object that contains the cursor used for pagination + in order to fetch the next page of results. + response: ListUsersPaginationResponse + + listWithOffsetPagination: + pagination: + offset: $request.page + results: $response.data + method: GET + path: "" + request: + name: ListUsersOffsetPaginationRequest + query-parameters: + page: + type: optional + docs: Defaults to first page + per_page: + type: optional + docs: Defaults to per page + order: + type: optional + starting_after: + type: optional + docs: | + The cursor used for pagination in order to fetch + the next page of results. + response: ListUsersPaginationResponse + + listWithBodyOffsetPagination: + pagination: + offset: $request.pagination.page + results: $response.data + method: POST + path: "" + request: + name: ListUsersBodyOffsetPaginationRequest + body: + properties: + pagination: + type: optional + docs: | + The object that contains the offset used for pagination + in order to fetch the next page of results. + response: ListUsersPaginationResponse + + listWithOffsetStepPagination: + pagination: + offset: $request.page + results: $response.data + step: $request.limit + method: GET + path: "" + request: + name: ListUsersOffsetStepPaginationRequest + query-parameters: + page: + type: optional + docs: Defaults to first page + limit: + type: optional + docs: | + The maxiumum number of elements to return. + This is also used as the step size in this + paginated endpoint. + order: + type: optional + response: ListUsersPaginationResponse + + listWithOffsetPaginationHasNextPage: + pagination: + offset: $request.page + results: $response.data + step: $request.limit + has-next-page: $response.hasNextPage + method: GET + path: "" + request: + name: ListWithOffsetPaginationHasNextPageRequest + query-parameters: + page: + type: optional + docs: Defaults to first page + limit: + type: optional + docs: | + The maxiumum number of elements to return. + This is also used as the step size in this + paginated endpoint. + order: + type: optional + response: ListUsersPaginationResponse + + listWithExtendedResults: + pagination: + cursor: $request.cursor + next_cursor: $response.next + results: $response.data.users + method: GET + path: "" + request: + name: ListUsersExtendedRequest + query-parameters: + cursor: optional + response: ListUsersExtendedResponse + + listWithExtendedResultsAndOptionalData: + pagination: + cursor: $request.cursor + next_cursor: $response.next + results: $response.data.users + method: GET + path: "" + request: + name: ListUsersExtendedRequestForOptionalData + query-parameters: + cursor: optional + response: ListUsersExtendedOptionalListResponse + + listUsernames: + pagination: + cursor: $request.starting_after + next_cursor: $response.cursor.after + results: $response.cursor.data + method: GET + path: "" + request: + name: ListUsernamesRequest + query-parameters: + starting_after: + type: optional + docs: | + The cursor used for pagination in order to fetch + the next page of results. + response: root.UsernameCursor + + listWithGlobalConfig: + method: GET + path: "" + pagination: true + request: + name: ListWithGlobalConfigRequest + query-parameters: + offset: + type: optional + response: UsernameContainer \ No newline at end of file diff --git a/seed/pydantic-v2/pagination/.mock/fern.config.json b/seed/pydantic-v2/pagination/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/pagination/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/pagination/.mock/generators.yml b/seed/pydantic-v2/pagination/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/pagination/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/pagination/resources/users/types/list_users_extended_optional_list_response.py b/seed/pydantic-v2/pagination/resources/users/types/list_users_extended_optional_list_response.py new file mode 100644 index 00000000000..4c3fffebb73 --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/list_users_extended_optional_list_response.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel +from resources.users.types.user_optional_list_page import UserOptionalListPage +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ListUsersExtendedOptionalListResponse(BaseModel, UserOptionalListPage): + total_count: int + """ + The totall number of /users + """ + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/list_users_extended_response.py b/seed/pydantic-v2/pagination/resources/users/types/list_users_extended_response.py new file mode 100644 index 00000000000..e08990da151 --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/list_users_extended_response.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel +from resources.users.types.user_page import UserPage +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ListUsersExtendedResponse(BaseModel, UserPage): + total_count: int + """ + The totall number of /users + """ + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/list_users_pagination_response.py b/seed/pydantic-v2/pagination/resources/users/types/list_users_pagination_response.py new file mode 100644 index 00000000000..73be1705ba4 --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/list_users_pagination_response.py @@ -0,0 +1,21 @@ +from pydantic import BaseModel +from typing import Optional, List +from resources.users.types.page import Page +from resources.users.types.user import User +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class ListUsersPaginationResponse(BaseModel): + has_next_page: Optional[bool] + page: Optional[Page] = None + total_count: int + """ + The totall number of /users + """ + data: List[User] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/next_page.py b/seed/pydantic-v2/pagination/resources/users/types/next_page.py new file mode 100644 index 00000000000..c6c225a82a9 --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/next_page.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class NextPage(BaseModel): + page: int + starting_after: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/page.py b/seed/pydantic-v2/pagination/resources/users/types/page.py new file mode 100644 index 00000000000..9081cb99161 --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/page.py @@ -0,0 +1,20 @@ +from pydantic import BaseModel +from typing import Optional +from resources.users.types.next_page import NextPage +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Page(BaseModel): + page: int + """ + The current page + """ + next: Optional[NextPage] = None + per_page: int + total_page: int + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/user.py b/seed/pydantic-v2/pagination/resources/users/types/user.py new file mode 100644 index 00000000000..8d8d8a0a5e9 --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/user.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class User(BaseModel): + name: str + id: int + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/user_list_container.py b/seed/pydantic-v2/pagination/resources/users/types/user_list_container.py new file mode 100644 index 00000000000..0eeee94a95b --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/user_list_container.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import List +from resources.users.types.user import User +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UserListContainer(BaseModel): + users: List[User] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/user_optional_list_container.py b/seed/pydantic-v2/pagination/resources/users/types/user_optional_list_container.py new file mode 100644 index 00000000000..b70539d4733 --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/user_optional_list_container.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional, List +from resources.users.types.user import User +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UserOptionalListContainer(BaseModel): + users: Optional[List[User]] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/user_optional_list_page.py b/seed/pydantic-v2/pagination/resources/users/types/user_optional_list_page.py new file mode 100644 index 00000000000..51c2f4f8eec --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/user_optional_list_page.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel +from resources.users.types.user_optional_list_container import UserOptionalListContainer +from typing import Optional +from uuid import UUID +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UserOptionalListPage(BaseModel): + data: UserOptionalListContainer + next: Optional[UUID] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/user_page.py b/seed/pydantic-v2/pagination/resources/users/types/user_page.py new file mode 100644 index 00000000000..ce44a773271 --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/user_page.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel +from resources.users.types.user_list_container import UserListContainer +from typing import Optional +from uuid import UUID +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UserPage(BaseModel): + data: UserListContainer + next: Optional[UUID] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/username_container.py b/seed/pydantic-v2/pagination/resources/users/types/username_container.py new file mode 100644 index 00000000000..6cb13b375f9 --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/username_container.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import List +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UsernameContainer(BaseModel): + results: List[str] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/with_cursor.py b/seed/pydantic-v2/pagination/resources/users/types/with_cursor.py new file mode 100644 index 00000000000..dc9217c8d72 --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/with_cursor.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class WithCursor(BaseModel): + cursor: Optional[str] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/resources/users/types/with_page.py b/seed/pydantic-v2/pagination/resources/users/types/with_page.py new file mode 100644 index 00000000000..29e06706743 --- /dev/null +++ b/seed/pydantic-v2/pagination/resources/users/types/with_page.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class WithPage(BaseModel): + page: Optional[int] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/snippet-templates.json b/seed/pydantic-v2/pagination/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/pagination/snippet.json b/seed/pydantic-v2/pagination/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/pagination/types/username_cursor.py b/seed/pydantic-v2/pagination/types/username_cursor.py new file mode 100644 index 00000000000..1f3b22f78e1 --- /dev/null +++ b/seed/pydantic-v2/pagination/types/username_cursor.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from .types.username_page import UsernamePage +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UsernameCursor(BaseModel): + cursor: UsernamePage + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/pagination/types/username_page.py b/seed/pydantic-v2/pagination/types/username_page.py new file mode 100644 index 00000000000..09f5f74032e --- /dev/null +++ b/seed/pydantic-v2/pagination/types/username_page.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional, List +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class UsernamePage(BaseModel): + after: Optional[str] = None + data: List[str] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/plain-text/.mock/definition/api.yml b/seed/pydantic-v2/plain-text/.mock/definition/api.yml new file mode 100644 index 00000000000..4ee1d9980a2 --- /dev/null +++ b/seed/pydantic-v2/plain-text/.mock/definition/api.yml @@ -0,0 +1 @@ +name: plain-text diff --git a/seed/pydantic-v2/plain-text/.mock/definition/service.yml b/seed/pydantic-v2/plain-text/.mock/definition/service.yml new file mode 100644 index 00000000000..c42c866bcc9 --- /dev/null +++ b/seed/pydantic-v2/plain-text/.mock/definition/service.yml @@ -0,0 +1,8 @@ +service: + auth: false + base-path: "" + endpoints: + getText: + path: /text + method: POST + response: text diff --git a/seed/pydantic-v2/plain-text/.mock/fern.config.json b/seed/pydantic-v2/plain-text/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/plain-text/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/plain-text/.mock/generators.yml b/seed/pydantic-v2/plain-text/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/plain-text/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/plain-text/snippet-templates.json b/seed/pydantic-v2/plain-text/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/plain-text/snippet.json b/seed/pydantic-v2/plain-text/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/query-parameters/.mock/definition/api.yml b/seed/pydantic-v2/query-parameters/.mock/definition/api.yml new file mode 100644 index 00000000000..f5aa88ee4e4 --- /dev/null +++ b/seed/pydantic-v2/query-parameters/.mock/definition/api.yml @@ -0,0 +1 @@ +name: query-parameters diff --git a/seed/pydantic-v2/query-parameters/.mock/definition/user.yml b/seed/pydantic-v2/query-parameters/.mock/definition/user.yml new file mode 100644 index 00000000000..74eb0d08526 --- /dev/null +++ b/seed/pydantic-v2/query-parameters/.mock/definition/user.yml @@ -0,0 +1,39 @@ +types: + User: + properties: + name: string + tags: list + NestedUser: + properties: + name: string + user: User + +service: + base-path: /user + auth: false + endpoints: + getUsername: + path: "" + method: GET + request: + name: GetUsersRequest + query-parameters: + limit: integer + id: uuid + date: date + deadline: datetime + bytes: base64 + user: User + userList: list + optionalDeadline: optional + keyValue: map + optionalString: optional + nestedUser: NestedUser + optionalUser: optional + excludeUser: + type: User + allow-multiple: true + filter: + type: string + allow-multiple: true + response: User diff --git a/seed/pydantic-v2/query-parameters/.mock/fern.config.json b/seed/pydantic-v2/query-parameters/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/query-parameters/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/query-parameters/.mock/generators.yml b/seed/pydantic-v2/query-parameters/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/query-parameters/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/query-parameters/resources/user/types/nested_user.py b/seed/pydantic-v2/query-parameters/resources/user/types/nested_user.py new file mode 100644 index 00000000000..5d37f8cf37e --- /dev/null +++ b/seed/pydantic-v2/query-parameters/resources/user/types/nested_user.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from resources.user.types.user import User +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class NestedUser(BaseModel): + name: str + user: User + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/query-parameters/resources/user/types/user.py b/seed/pydantic-v2/query-parameters/resources/user/types/user.py new file mode 100644 index 00000000000..c6f06633616 --- /dev/null +++ b/seed/pydantic-v2/query-parameters/resources/user/types/user.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import List +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class User(BaseModel): + name: str + tags: List[str] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/query-parameters/snippet-templates.json b/seed/pydantic-v2/query-parameters/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/query-parameters/snippet.json b/seed/pydantic-v2/query-parameters/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/reserved-keywords/.mock/definition/api.yml b/seed/pydantic-v2/reserved-keywords/.mock/definition/api.yml new file mode 100644 index 00000000000..db5bb47ddd7 --- /dev/null +++ b/seed/pydantic-v2/reserved-keywords/.mock/definition/api.yml @@ -0,0 +1,5 @@ +name: nursery-api + +error-discrimination: + strategy: property + property-name: errorName diff --git a/seed/pydantic-v2/reserved-keywords/.mock/definition/package.yml b/seed/pydantic-v2/reserved-keywords/.mock/definition/package.yml new file mode 100644 index 00000000000..a2328bf1a8e --- /dev/null +++ b/seed/pydantic-v2/reserved-keywords/.mock/definition/package.yml @@ -0,0 +1,20 @@ +types: + Package: + properties: + name: string + Record: + properties: + foo: map + 3d: integer + +service: + base-path: / + auth: false + endpoints: + test: + method: POST + path: "" + request: + name: TestRequest + query-parameters: + for: string diff --git a/seed/pydantic-v2/reserved-keywords/.mock/fern.config.json b/seed/pydantic-v2/reserved-keywords/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/reserved-keywords/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/reserved-keywords/.mock/generators.yml b/seed/pydantic-v2/reserved-keywords/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/reserved-keywords/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/reserved-keywords/.mock/sdk-reserved-keywords.shot b/seed/pydantic-v2/reserved-keywords/.mock/sdk-reserved-keywords.shot new file mode 100644 index 00000000000..142f0565e78 --- /dev/null +++ b/seed/pydantic-v2/reserved-keywords/.mock/sdk-reserved-keywords.shot @@ -0,0 +1,3552 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`runGenerator reserved-keywords 1`] = ` +Array [ + Object { + "contents": "/** + * This file was auto-generated by Fern from our API Definition. + */ +import * as core from \\"./core\\"; +import { Package } from \\"./api/resources/package/client/Client\\"; +export declare namespace FernApiClient { + interface Options { + environment: core.Supplier; + } + interface RequestOptions { + timeoutInSeconds?: number; + } +} +export declare class FernApiClient { + protected readonly _options: FernApiClient.Options; + constructor(_options: FernApiClient.Options); + protected _package: Package | undefined; + get package(): Package; +} +", + "name": "Client.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +/** + * This file was auto-generated by Fern from our API Definition. + */ +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.FernApiClient = void 0; +const Client_1 = require(\\"./api/resources/package/client/Client\\"); +class FernApiClient { + constructor(_options) { + this._options = _options; + } + get package() { + var _a; + return ((_a = this._package) !== null && _a !== void 0 ? _a : (this._package = new Client_1.Package(this._options))); + } +} +exports.FernApiClient = FernApiClient; +", + "name": "Client.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": "export * from \\"./resources\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +__exportStar(require(\\"./resources\\"), exports); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": "export * as package_ from \\"./package\\"; +export * from \\"./package/types\\"; +export * from \\"./package/client/requests\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, \\"default\\", { enumerable: true, value: v }); +}) : function(o, v) { + o[\\"default\\"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== \\"default\\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.package_ = void 0; +exports.package_ = __importStar(require(\\"./package\\")); +__exportStar(require(\\"./package/types\\"), exports); +__exportStar(require(\\"./package/client/requests\\"), exports); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": Array [ + Object { + "contents": "/** + * This file was auto-generated by Fern from our API Definition. + */ +import * as core from \\"../../../../core\\"; +import * as FernApi from \\"../../..\\"; +export declare namespace Package { + interface Options { + environment: core.Supplier; + } + interface RequestOptions { + timeoutInSeconds?: number; + } +} +export declare class Package { + protected readonly _options: Package.Options; + constructor(_options: Package.Options); + test(request: FernApi.TestRequest, requestOptions?: Package.RequestOptions): Promise>; +} +", + "name": "Client.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +/** + * This file was auto-generated by Fern from our API Definition. + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, \\"default\\", { enumerable: true, value: v }); +}) : function(o, v) { + o[\\"default\\"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== \\"default\\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { \\"default\\": mod }; +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.Package = void 0; +const core = __importStar(require(\\"../../../../core\\")); +const FernApi = __importStar(require(\\"../../..\\")); +const url_search_params_1 = __importDefault(require(\\"@ungap/url-search-params\\")); +class Package { + constructor(_options) { + this._options = _options; + } + test(request, requestOptions) { + return __awaiter(this, void 0, void 0, function* () { + const { for: for_ } = request; + const _queryParams = new url_search_params_1.default(); + _queryParams.append(\\"for\\", for_); + const _response = yield core.fetcher({ + url: yield core.Supplier.get(this._options.environment), + method: \\"POST\\", + headers: { + \\"X-Fern-Language\\": \\"JavaScript\\", + }, + contentType: \\"application/json\\", + queryParameters: _queryParams, + timeoutMs: (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.timeoutInSeconds) != null ? requestOptions.timeoutInSeconds * 1000 : 60000, + }); + if (_response.ok) { + return { + ok: true, + body: undefined, + }; + } + return { + ok: false, + error: FernApi.package_.test.Error._unknown(_response.error), + }; + }); + } +} +exports.Package = Package; +", + "name": "Client.js", + "type": "file", + }, + Object { + "contents": "export * from \\"./requests\\"; +export * as test from \\"./test\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, \\"default\\", { enumerable: true, value: v }); +}) : function(o, v) { + o[\\"default\\"] = v; +}); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== \\"default\\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.test = void 0; +__exportStar(require(\\"./requests\\"), exports); +exports.test = __importStar(require(\\"./test\\")); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": "/** + * This file was auto-generated by Fern from our API Definition. + */ +export interface TestRequest { + for: string; +} +", + "name": "TestRequest.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +/** + * This file was auto-generated by Fern from our API Definition. + */ +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "TestRequest.js", + "type": "file", + }, + Object { + "contents": "export { TestRequest } from \\"./TestRequest\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "index.js", + "type": "file", + }, + ], + "name": "requests", + "type": "directory", + }, + Object { + "contents": "/** + * This file was auto-generated by Fern from our API Definition. + */ +import * as FernApi from \\"../../..\\"; +import * as core from \\"../../../../core\\"; +export declare type Error = FernApi.package_.test.Error._Unknown; +export declare namespace Error { + interface _Unknown extends _Utils { + errorName: void; + content: core.Fetcher.Error; + } + interface _Utils { + _visit: <_Result>(visitor: FernApi.package_.test.Error._Visitor<_Result>) => _Result; + } + interface _Visitor<_Result> { + _other: (value: core.Fetcher.Error) => _Result; + } +} +export declare const Error: { + readonly _unknown: (fetcherError: core.Fetcher.Error) => FernApi.package_.test.Error._Unknown; + readonly _visit: <_Result>(value: FernApi.package_.test.Error, visitor: FernApi.package_.test.Error._Visitor<_Result>) => _Result; +}; +", + "name": "test.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +/** + * This file was auto-generated by Fern from our API Definition. + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, \\"default\\", { enumerable: true, value: v }); +}) : function(o, v) { + o[\\"default\\"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== \\"default\\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.Error = void 0; +const FernApi = __importStar(require(\\"../../..\\")); +exports.Error = { + _unknown: (fetcherError) => { + return { + errorName: undefined, + content: fetcherError, + _visit: function (visitor) { + return FernApi.package_.test.Error._visit(this, visitor); + }, + }; + }, + _visit: (value, visitor) => { + switch (value.errorName) { + default: + return visitor._other(value); + } + }, +}; +", + "name": "test.js", + "type": "file", + }, + ], + "name": "client", + "type": "directory", + }, + Object { + "contents": "export * from \\"./types\\"; +export * from \\"./client\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +__exportStar(require(\\"./types\\"), exports); +__exportStar(require(\\"./client\\"), exports); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": "/** + * This file was auto-generated by Fern from our API Definition. + */ +export interface Package { + name: string; +} +", + "name": "Package.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +/** + * This file was auto-generated by Fern from our API Definition. + */ +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "Package.js", + "type": "file", + }, + Object { + "contents": "/** + * This file was auto-generated by Fern from our API Definition. + */ +export interface Record_ { + foo: Record; + \\"3D\\": number; +} +", + "name": "Record_.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +/** + * This file was auto-generated by Fern from our API Definition. + */ +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "Record_.js", + "type": "file", + }, + Object { + "contents": "export * from \\"./Package\\"; +export * from \\"./Record_\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +__exportStar(require(\\"./Package\\"), exports); +__exportStar(require(\\"./Record_\\"), exports); +", + "name": "index.js", + "type": "file", + }, + ], + "name": "types", + "type": "directory", + }, + ], + "name": "package", + "type": "directory", + }, + ], + "name": "resources", + "type": "directory", + }, + ], + "name": "api", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": Array [ + Object { + "contents": "export declare type APIResponse = SuccessfulResponse | FailedResponse; +export interface SuccessfulResponse { + ok: true; + body: T; +} +export interface FailedResponse { + ok: false; + error: T; +} +", + "name": "APIResponse.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "APIResponse.js", + "type": "file", + }, + Object { + "contents": "import { default as URLSearchParams } from \\"@ungap/url-search-params\\"; +import { AxiosAdapter } from \\"axios\\"; +import { APIResponse } from \\"./APIResponse\\"; +export declare type FetchFunction = (args: Fetcher.Args) => Promise>; +export declare namespace Fetcher { + interface Args { + url: string; + method: string; + contentType?: string; + headers?: Record; + queryParameters?: URLSearchParams; + body?: unknown; + timeoutMs?: number; + withCredentials?: boolean; + responseType?: \\"json\\" | \\"blob\\"; + adapter?: AxiosAdapter; + onUploadProgress?: (event: ProgressEvent) => void; + } + type Error = FailedStatusCodeError | NonJsonError | TimeoutError | UnknownError; + interface FailedStatusCodeError { + reason: \\"status-code\\"; + statusCode: number; + body: unknown; + } + interface NonJsonError { + reason: \\"non-json\\"; + statusCode: number; + rawBody: string; + } + interface TimeoutError { + reason: \\"timeout\\"; + } + interface UnknownError { + reason: \\"unknown\\"; + errorMessage: string; + } +} +export declare const fetcher: FetchFunction; +", + "name": "Fetcher.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { \\"default\\": mod }; +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.fetcher = void 0; +const axios_1 = __importDefault(require(\\"axios\\")); +const axios_retry_1 = __importDefault(require(\\"axios-retry\\")); +const INITIAL_RETRY_DELAY = 1; +const MAX_RETRY_DELAY = 60; +const MAX_RETRIES = 5; +const AXIOS = axios_1.default.create(); +function fetcherImpl(args) { + var _a, _b; + return __awaiter(this, void 0, void 0, function* () { + const headers = {}; + if (args.body !== undefined && args.contentType != null) { + headers[\\"Content-Type\\"] = args.contentType; + } + if (args.headers != null) { + for (const [key, value] of Object.entries(args.headers)) { + if (value != null) { + headers[key] = value; + } + } + } + (0, axios_retry_1.default)(AXIOS, { + retries: MAX_RETRIES, + retryCondition: (error) => { + return error.response != null && [500, 502, 429].includes(error.response.status); + }, + retryDelay: (count) => { + if (count == 0) { + return INITIAL_RETRY_DELAY; + } + // Apply exponential backoff, but not more than the max. + return Math.min(INITIAL_RETRY_DELAY * Math.pow(count - 1, 2), MAX_RETRY_DELAY); + }, + }); + try { + const response = yield AXIOS.request({ + url: args.url, + params: args.queryParameters, + method: args.method, + headers, + data: args.body, + validateStatus: () => true, + transformResponse: (response) => response, + timeout: args.timeoutMs, + transitional: { + clarifyTimeoutError: true, + }, + withCredentials: args.withCredentials, + adapter: args.adapter, + onUploadProgress: args.onUploadProgress, + maxBodyLength: Infinity, + maxContentLength: Infinity, + responseType: (_a = args.responseType) !== null && _a !== void 0 ? _a : \\"json\\", + }); + let body; + if (args.responseType === \\"blob\\") { + body = response.data; + } + else if (response.data != null && response.data.length > 0) { + try { + body = (_b = JSON.parse(response.data)) !== null && _b !== void 0 ? _b : undefined; + } + catch (_c) { + return { + ok: false, + error: { + reason: \\"non-json\\", + statusCode: response.status, + rawBody: response.data, + }, + }; + } + } + if (response.status >= 200 && response.status < 400) { + return { + ok: true, + body: body, + }; + } + else { + return { + ok: false, + error: { + reason: \\"status-code\\", + statusCode: response.status, + body, + }, + }; + } + } + catch (error) { + if (error.code === \\"ETIMEDOUT\\") { + return { + ok: false, + error: { + reason: \\"timeout\\", + }, + }; + } + return { + ok: false, + error: { + reason: \\"unknown\\", + errorMessage: error.message, + }, + }; + } + }); +} +exports.fetcher = fetcherImpl; +", + "name": "Fetcher.js", + "type": "file", + }, + Object { + "contents": "export declare type Supplier = T | Promise | (() => T | Promise); +export declare const Supplier: { + get: (supplier: Supplier) => Promise; +}; +", + "name": "Supplier.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.Supplier = void 0; +exports.Supplier = { + get: (supplier) => __awaiter(void 0, void 0, void 0, function* () { + if (typeof supplier === \\"function\\") { + return supplier(); + } + else { + return supplier; + } + }), +}; +", + "name": "Supplier.js", + "type": "file", + }, + Object { + "contents": "export type { APIResponse } from \\"./APIResponse\\"; +export { fetcher } from \\"./Fetcher\\"; +export type { Fetcher, FetchFunction } from \\"./Fetcher\\"; +export { Supplier } from \\"./Supplier\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.Supplier = exports.fetcher = void 0; +var Fetcher_1 = require(\\"./Fetcher\\"); +Object.defineProperty(exports, \\"fetcher\\", { enumerable: true, get: function () { return Fetcher_1.fetcher; } }); +var Supplier_1 = require(\\"./Supplier\\"); +Object.defineProperty(exports, \\"Supplier\\", { enumerable: true, get: function () { return Supplier_1.Supplier; } }); +", + "name": "index.js", + "type": "file", + }, + ], + "name": "fetcher", + "type": "directory", + }, + Object { + "contents": "export * from \\"./fetcher\\"; +export * as serialization from \\"./schemas\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, \\"default\\", { enumerable: true, value: v }); +}) : function(o, v) { + o[\\"default\\"] = v; +}); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== \\"default\\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.serialization = void 0; +__exportStar(require(\\"./fetcher\\"), exports); +exports.serialization = __importStar(require(\\"./schemas\\")); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": "import { SchemaUtils } from \\"./builders\\"; +import { MaybePromise } from \\"./utils/MaybePromise\\"; +export declare type Schema = BaseSchema & SchemaUtils; +export declare type inferRaw = S extends Schema ? Raw : never; +export declare type inferParsed = S extends Schema ? Parsed : never; +export interface BaseSchema { + parse: (raw: unknown, opts?: SchemaOptions) => MaybePromise>; + json: (parsed: unknown, opts?: SchemaOptions) => MaybePromise>; + getType: () => SchemaType | Promise; +} +export declare const SchemaType: { + readonly DATE: \\"date\\"; + readonly ENUM: \\"enum\\"; + readonly LIST: \\"list\\"; + readonly STRING_LITERAL: \\"stringLiteral\\"; + readonly OBJECT: \\"object\\"; + readonly ANY: \\"any\\"; + readonly BOOLEAN: \\"boolean\\"; + readonly NUMBER: \\"number\\"; + readonly STRING: \\"string\\"; + readonly UNKNOWN: \\"unknown\\"; + readonly RECORD: \\"record\\"; + readonly SET: \\"set\\"; + readonly UNION: \\"union\\"; + readonly UNDISCRIMINATED_UNION: \\"undiscriminatedUnion\\"; + readonly OPTIONAL: \\"optional\\"; +}; +export declare type SchemaType = typeof SchemaType[keyof typeof SchemaType]; +export declare type MaybeValid = Valid | Invalid; +export interface Valid { + ok: true; + value: T; +} +export interface Invalid { + ok: false; + errors: ValidationError[]; +} +export interface ValidationError { + path: string[]; + message: string; +} +export interface SchemaOptions { + /** + * how to handle unrecognized keys in objects + * + * @default \\"fail\\" + */ + unrecognizedObjectKeys?: \\"fail\\" | \\"passthrough\\" | \\"strip\\"; + /** + * whether to fail when an unrecognized discriminant value is + * encountered in a union + * + * @default false + */ + allowUnrecognizedUnionMembers?: boolean; + /** + * whether to fail when an unrecognized enum value is encountered + * + * @default false + */ + allowUnrecognizedEnumValues?: boolean; + /** + * whether to allow data that doesn't conform to the schema. + * invalid data is passed through without transformation. + * + * when this is enabled, .parse() and .json() will always + * return \`ok: true\`. \`.parseOrThrow()\` and \`.jsonOrThrow()\` + * will never fail. + * + * @default false + */ + skipValidation?: boolean; + /** + * each validation failure contains a \\"path\\" property, which is + * the breadcrumbs to the offending node in the JSON. you can supply + * a prefix that is prepended to all the errors' paths. this can be + * helpful for zurg's internal debug logging. + */ + breadcrumbsPrefix?: string[]; +} +", + "name": "Schema.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.SchemaType = void 0; +exports.SchemaType = { + DATE: \\"date\\", + ENUM: \\"enum\\", + LIST: \\"list\\", + STRING_LITERAL: \\"stringLiteral\\", + OBJECT: \\"object\\", + ANY: \\"any\\", + BOOLEAN: \\"boolean\\", + NUMBER: \\"number\\", + STRING: \\"string\\", + UNKNOWN: \\"unknown\\", + RECORD: \\"record\\", + SET: \\"set\\", + UNION: \\"union\\", + UNDISCRIMINATED_UNION: \\"undiscriminatedUnion\\", + OPTIONAL: \\"optional\\", +}; +", + "name": "Schema.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": Array [ + Object { + "contents": "import { Schema } from \\"../../Schema\\"; +export declare function date(): Schema; +", + "name": "date.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.date = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +const maybeSkipValidation_1 = require(\\"../../utils/maybeSkipValidation\\"); +const schema_utils_1 = require(\\"../schema-utils\\"); +// https://stackoverflow.com/questions/12756159/regex-and-iso8601-formatted-datetime +const ISO_8601_REGEX = /^([+-]?\\\\d{4}(?!\\\\d{2}\\\\b))((-?)((0[1-9]|1[0-2])(\\\\3([12]\\\\d|0[1-9]|3[01]))?|W([0-4]\\\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\\\d|[12]\\\\d{2}|3([0-5]\\\\d|6[1-6])))([T\\\\s]((([01]\\\\d|2[0-3])((:?)[0-5]\\\\d)?|24:?00)([.,]\\\\d+(?!:))?)?(\\\\17[0-5]\\\\d([.,]\\\\d+)?)?([zZ]|([+-])([01]\\\\d|2[0-3]):?([0-5]\\\\d)?)?)?)?$/; +function date() { + const baseSchema = { + parse: (raw, { breadcrumbsPrefix = [] } = {}) => { + if (typeof raw !== \\"string\\") { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(raw, \\"string\\"), + }, + ], + }; + } + if (!ISO_8601_REGEX.test(raw)) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(raw, \\"ISO 8601 date string\\"), + }, + ], + }; + } + return { + ok: true, + value: new Date(raw), + }; + }, + json: (date, { breadcrumbsPrefix = [] } = {}) => { + if (date instanceof Date) { + return { + ok: true, + value: date.toISOString(), + }; + } + else { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(date, \\"Date object\\"), + }, + ], + }; + } + }, + getType: () => Schema_1.SchemaType.DATE, + }; + return Object.assign(Object.assign({}, (0, maybeSkipValidation_1.maybeSkipValidation)(baseSchema)), (0, schema_utils_1.getSchemaUtils)(baseSchema)); +} +exports.date = date; +", + "name": "date.js", + "type": "file", + }, + Object { + "contents": "export { date } from \\"./date\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.date = void 0; +var date_1 = require(\\"./date\\"); +Object.defineProperty(exports, \\"date\\", { enumerable: true, get: function () { return date_1.date; } }); +", + "name": "index.js", + "type": "file", + }, + ], + "name": "date", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": "import { Schema } from \\"../../Schema\\"; +export declare function enum_(values: E): Schema; +", + "name": "enum.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.enum_ = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const createIdentitySchemaCreator_1 = require(\\"../../utils/createIdentitySchemaCreator\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +function enum_(values) { + const validValues = new Set(values); + const schemaCreator = (0, createIdentitySchemaCreator_1.createIdentitySchemaCreator)(Schema_1.SchemaType.ENUM, (value, { allowUnrecognizedEnumValues, breadcrumbsPrefix = [] } = {}) => { + if (typeof value !== \\"string\\") { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(value, \\"string\\"), + }, + ], + }; + } + if (!validValues.has(value) && !allowUnrecognizedEnumValues) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(value, \\"enum\\"), + }, + ], + }; + } + return { + ok: true, + value: value, + }; + }); + return schemaCreator(); +} +exports.enum_ = enum_; +", + "name": "enum.js", + "type": "file", + }, + Object { + "contents": "export { enum_ } from \\"./enum\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.enum_ = void 0; +var enum_1 = require(\\"./enum\\"); +Object.defineProperty(exports, \\"enum_\\", { enumerable: true, get: function () { return enum_1.enum_; } }); +", + "name": "index.js", + "type": "file", + }, + ], + "name": "enum", + "type": "directory", + }, + Object { + "contents": "export * from \\"./date\\"; +export * from \\"./enum\\"; +export * from \\"./lazy\\"; +export * from \\"./list\\"; +export * from \\"./literals\\"; +export * from \\"./object\\"; +export * from \\"./object-like\\"; +export * from \\"./primitives\\"; +export * from \\"./record\\"; +export * from \\"./schema-utils\\"; +export * from \\"./set\\"; +export * from \\"./undiscriminated-union\\"; +export * from \\"./union\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +__exportStar(require(\\"./date\\"), exports); +__exportStar(require(\\"./enum\\"), exports); +__exportStar(require(\\"./lazy\\"), exports); +__exportStar(require(\\"./list\\"), exports); +__exportStar(require(\\"./literals\\"), exports); +__exportStar(require(\\"./object\\"), exports); +__exportStar(require(\\"./object-like\\"), exports); +__exportStar(require(\\"./primitives\\"), exports); +__exportStar(require(\\"./record\\"), exports); +__exportStar(require(\\"./schema-utils\\"), exports); +__exportStar(require(\\"./set\\"), exports); +__exportStar(require(\\"./undiscriminated-union\\"), exports); +__exportStar(require(\\"./union\\"), exports); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": "export { lazy } from \\"./lazy\\"; +export type { SchemaGetter } from \\"./lazy\\"; +export { lazyObject } from \\"./lazyObject\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.lazyObject = exports.lazy = void 0; +var lazy_1 = require(\\"./lazy\\"); +Object.defineProperty(exports, \\"lazy\\", { enumerable: true, get: function () { return lazy_1.lazy; } }); +var lazyObject_1 = require(\\"./lazyObject\\"); +Object.defineProperty(exports, \\"lazyObject\\", { enumerable: true, get: function () { return lazyObject_1.lazyObject; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": "import { BaseSchema, Schema } from \\"../../Schema\\"; +export declare type SchemaGetter> = () => SchemaType | Promise; +export declare function lazy(getter: SchemaGetter>): Schema; +export declare function constructLazyBaseSchema(getter: SchemaGetter>): BaseSchema; +export declare function getMemoizedSchema>(getter: SchemaGetter): Promise; +", + "name": "lazy.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.getMemoizedSchema = exports.constructLazyBaseSchema = exports.lazy = void 0; +const schema_utils_1 = require(\\"../schema-utils\\"); +function lazy(getter) { + const baseSchema = constructLazyBaseSchema(getter); + return Object.assign(Object.assign({}, baseSchema), (0, schema_utils_1.getSchemaUtils)(baseSchema)); +} +exports.lazy = lazy; +function constructLazyBaseSchema(getter) { + return { + parse: (raw, opts) => __awaiter(this, void 0, void 0, function* () { return (yield getMemoizedSchema(getter)).parse(raw, opts); }), + json: (parsed, opts) => __awaiter(this, void 0, void 0, function* () { return (yield getMemoizedSchema(getter)).json(parsed, opts); }), + getType: () => __awaiter(this, void 0, void 0, function* () { return (yield getMemoizedSchema(getter)).getType(); }), + }; +} +exports.constructLazyBaseSchema = constructLazyBaseSchema; +function getMemoizedSchema(getter) { + return __awaiter(this, void 0, void 0, function* () { + const castedGetter = getter; + if (castedGetter.__zurg_memoized == null) { + castedGetter.__zurg_memoized = yield getter(); + } + return castedGetter.__zurg_memoized; + }); +} +exports.getMemoizedSchema = getMemoizedSchema; +", + "name": "lazy.js", + "type": "file", + }, + Object { + "contents": "import { ObjectSchema } from \\"../object/types\\"; +import { SchemaGetter } from \\"./lazy\\"; +export declare function lazyObject(getter: SchemaGetter>): ObjectSchema; +", + "name": "lazyObject.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.lazyObject = void 0; +const object_1 = require(\\"../object\\"); +const object_like_1 = require(\\"../object-like\\"); +const schema_utils_1 = require(\\"../schema-utils\\"); +const lazy_1 = require(\\"./lazy\\"); +function lazyObject(getter) { + const baseSchema = Object.assign(Object.assign({}, (0, lazy_1.constructLazyBaseSchema)(getter)), { _getRawProperties: () => __awaiter(this, void 0, void 0, function* () { return (yield (0, lazy_1.getMemoizedSchema)(getter))._getRawProperties(); }), _getParsedProperties: () => __awaiter(this, void 0, void 0, function* () { return (yield (0, lazy_1.getMemoizedSchema)(getter))._getParsedProperties(); }) }); + return Object.assign(Object.assign(Object.assign(Object.assign({}, baseSchema), (0, schema_utils_1.getSchemaUtils)(baseSchema)), (0, object_like_1.getObjectLikeUtils)(baseSchema)), (0, object_1.getObjectUtils)(baseSchema)); +} +exports.lazyObject = lazyObject; +", + "name": "lazyObject.js", + "type": "file", + }, + ], + "name": "lazy", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": "export { list } from \\"./list\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.list = void 0; +var list_1 = require(\\"./list\\"); +Object.defineProperty(exports, \\"list\\", { enumerable: true, get: function () { return list_1.list; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": "import { Schema } from \\"../../Schema\\"; +export declare function list(schema: Schema): Schema; +", + "name": "list.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.list = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +const maybeSkipValidation_1 = require(\\"../../utils/maybeSkipValidation\\"); +const schema_utils_1 = require(\\"../schema-utils\\"); +function list(schema) { + const baseSchema = { + parse: (raw, opts) => __awaiter(this, void 0, void 0, function* () { + return validateAndTransformArray(raw, (item, index) => { + var _a; + return schema.parse(item, Object.assign(Object.assign({}, opts), { breadcrumbsPrefix: [...((_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : []), \`[\${index}]\`] })); + }); + }), + json: (parsed, opts) => validateAndTransformArray(parsed, (item, index) => { + var _a; + return schema.json(item, Object.assign(Object.assign({}, opts), { breadcrumbsPrefix: [...((_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : []), \`[\${index}]\`] })); + }), + getType: () => Schema_1.SchemaType.LIST, + }; + return Object.assign(Object.assign({}, (0, maybeSkipValidation_1.maybeSkipValidation)(baseSchema)), (0, schema_utils_1.getSchemaUtils)(baseSchema)); +} +exports.list = list; +function validateAndTransformArray(value, transformItem) { + return __awaiter(this, void 0, void 0, function* () { + if (!Array.isArray(value)) { + return { + ok: false, + errors: [ + { + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(value, \\"list\\"), + path: [], + }, + ], + }; + } + const maybeValidItems = yield Promise.all(value.map((item, index) => transformItem(item, index))); + return maybeValidItems.reduce((acc, item) => { + if (acc.ok && item.ok) { + return { + ok: true, + value: [...acc.value, item.value], + }; + } + const errors = []; + if (!acc.ok) { + errors.push(...acc.errors); + } + if (!item.ok) { + errors.push(...item.errors); + } + return { + ok: false, + errors, + }; + }, { ok: true, value: [] }); + }); +} +", + "name": "list.js", + "type": "file", + }, + ], + "name": "list", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": "export { stringLiteral } from \\"./stringLiteral\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.stringLiteral = void 0; +var stringLiteral_1 = require(\\"./stringLiteral\\"); +Object.defineProperty(exports, \\"stringLiteral\\", { enumerable: true, get: function () { return stringLiteral_1.stringLiteral; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": "import { Schema } from \\"../../Schema\\"; +export declare function stringLiteral(literal: V): Schema; +", + "name": "stringLiteral.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.stringLiteral = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const createIdentitySchemaCreator_1 = require(\\"../../utils/createIdentitySchemaCreator\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +function stringLiteral(literal) { + const schemaCreator = (0, createIdentitySchemaCreator_1.createIdentitySchemaCreator)(Schema_1.SchemaType.STRING_LITERAL, (value, { breadcrumbsPrefix = [] } = {}) => { + if (value === literal) { + return { + ok: true, + value: literal, + }; + } + else { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(value, \`\\"\${literal}\\"\`), + }, + ], + }; + } + }); + return schemaCreator(); +} +exports.stringLiteral = stringLiteral; +", + "name": "stringLiteral.js", + "type": "file", + }, + ], + "name": "literals", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": "export { getObjectUtils, object } from \\"./object\\"; +export { objectWithoutOptionalProperties } from \\"./objectWithoutOptionalProperties\\"; +export type { inferObjectWithoutOptionalPropertiesSchemaFromPropertySchemas, inferParsedObjectWithoutOptionalPropertiesFromPropertySchemas, } from \\"./objectWithoutOptionalProperties\\"; +export { isProperty, property } from \\"./property\\"; +export type { Property } from \\"./property\\"; +export type { BaseObjectSchema, inferObjectSchemaFromPropertySchemas, inferParsedObject, inferParsedObjectFromPropertySchemas, inferParsedPropertySchema, inferRawKey, inferRawObject, inferRawObjectFromPropertySchemas, inferRawPropertySchema, ObjectSchema, ObjectUtils, PropertySchemas, } from \\"./types\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.property = exports.isProperty = exports.objectWithoutOptionalProperties = exports.object = exports.getObjectUtils = void 0; +var object_1 = require(\\"./object\\"); +Object.defineProperty(exports, \\"getObjectUtils\\", { enumerable: true, get: function () { return object_1.getObjectUtils; } }); +Object.defineProperty(exports, \\"object\\", { enumerable: true, get: function () { return object_1.object; } }); +var objectWithoutOptionalProperties_1 = require(\\"./objectWithoutOptionalProperties\\"); +Object.defineProperty(exports, \\"objectWithoutOptionalProperties\\", { enumerable: true, get: function () { return objectWithoutOptionalProperties_1.objectWithoutOptionalProperties; } }); +var property_1 = require(\\"./property\\"); +Object.defineProperty(exports, \\"isProperty\\", { enumerable: true, get: function () { return property_1.isProperty; } }); +Object.defineProperty(exports, \\"property\\", { enumerable: true, get: function () { return property_1.property; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": "import { BaseObjectSchema, inferObjectSchemaFromPropertySchemas, ObjectUtils, PropertySchemas } from \\"./types\\"; +export declare function object>(schemas: T): inferObjectSchemaFromPropertySchemas; +export declare function getObjectUtils(schema: BaseObjectSchema): ObjectUtils; +", + "name": "object.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.getObjectUtils = exports.object = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const entries_1 = require(\\"../../utils/entries\\"); +const filterObject_1 = require(\\"../../utils/filterObject\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +const isPlainObject_1 = require(\\"../../utils/isPlainObject\\"); +const keys_1 = require(\\"../../utils/keys\\"); +const maybeSkipValidation_1 = require(\\"../../utils/maybeSkipValidation\\"); +const partition_1 = require(\\"../../utils/partition\\"); +const object_like_1 = require(\\"../object-like\\"); +const schema_utils_1 = require(\\"../schema-utils\\"); +const property_1 = require(\\"./property\\"); +function object(schemas) { + const baseSchema = { + _getRawProperties: () => Promise.resolve(Object.entries(schemas).map(([parsedKey, propertySchema]) => (0, property_1.isProperty)(propertySchema) ? propertySchema.rawKey : parsedKey)), + _getParsedProperties: () => Promise.resolve((0, keys_1.keys)(schemas)), + parse: (raw, opts) => __awaiter(this, void 0, void 0, function* () { + const rawKeyToProperty = {}; + const requiredKeys = []; + for (const [parsedKey, schemaOrObjectProperty] of (0, entries_1.entries)(schemas)) { + const rawKey = (0, property_1.isProperty)(schemaOrObjectProperty) ? schemaOrObjectProperty.rawKey : parsedKey; + const valueSchema = (0, property_1.isProperty)(schemaOrObjectProperty) + ? schemaOrObjectProperty.valueSchema + : schemaOrObjectProperty; + const property = { + rawKey, + parsedKey: parsedKey, + valueSchema, + }; + rawKeyToProperty[rawKey] = property; + if (yield isSchemaRequired(valueSchema)) { + requiredKeys.push(rawKey); + } + } + return validateAndTransformObject({ + value: raw, + requiredKeys, + getProperty: (rawKey) => { + const property = rawKeyToProperty[rawKey]; + if (property == null) { + return undefined; + } + return { + transformedKey: property.parsedKey, + transform: (propertyValue) => { + var _a; + return property.valueSchema.parse(propertyValue, Object.assign(Object.assign({}, opts), { breadcrumbsPrefix: [...((_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : []), rawKey] })); + }, + }; + }, + unrecognizedObjectKeys: opts === null || opts === void 0 ? void 0 : opts.unrecognizedObjectKeys, + skipValidation: opts === null || opts === void 0 ? void 0 : opts.skipValidation, + breadcrumbsPrefix: opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix, + }); + }), + json: (parsed, opts) => __awaiter(this, void 0, void 0, function* () { + const requiredKeys = []; + for (const [parsedKey, schemaOrObjectProperty] of (0, entries_1.entries)(schemas)) { + const valueSchema = (0, property_1.isProperty)(schemaOrObjectProperty) + ? schemaOrObjectProperty.valueSchema + : schemaOrObjectProperty; + if (yield isSchemaRequired(valueSchema)) { + requiredKeys.push(parsedKey); + } + } + return validateAndTransformObject({ + value: parsed, + requiredKeys, + getProperty: (parsedKey) => { + const property = schemas[parsedKey]; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (property == null) { + return undefined; + } + if ((0, property_1.isProperty)(property)) { + return { + transformedKey: property.rawKey, + transform: (propertyValue) => { + var _a; + return property.valueSchema.json(propertyValue, Object.assign(Object.assign({}, opts), { breadcrumbsPrefix: [...((_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : []), parsedKey] })); + }, + }; + } + else { + return { + transformedKey: parsedKey, + transform: (propertyValue) => { + var _a; + return property.json(propertyValue, Object.assign(Object.assign({}, opts), { breadcrumbsPrefix: [...((_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : []), parsedKey] })); + }, + }; + } + }, + unrecognizedObjectKeys: opts === null || opts === void 0 ? void 0 : opts.unrecognizedObjectKeys, + skipValidation: opts === null || opts === void 0 ? void 0 : opts.skipValidation, + breadcrumbsPrefix: opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix, + }); + }), + getType: () => Schema_1.SchemaType.OBJECT, + }; + return Object.assign(Object.assign(Object.assign(Object.assign({}, (0, maybeSkipValidation_1.maybeSkipValidation)(baseSchema)), (0, schema_utils_1.getSchemaUtils)(baseSchema)), (0, object_like_1.getObjectLikeUtils)(baseSchema)), getObjectUtils(baseSchema)); +} +exports.object = object; +function validateAndTransformObject({ value, requiredKeys, getProperty, unrecognizedObjectKeys = \\"fail\\", skipValidation = false, breadcrumbsPrefix = [], }) { + return __awaiter(this, void 0, void 0, function* () { + if (!(0, isPlainObject_1.isPlainObject)(value)) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(value, \\"object\\"), + }, + ], + }; + } + const missingRequiredKeys = new Set(requiredKeys); + const errors = []; + const transformed = {}; + for (const [preTransformedKey, preTransformedItemValue] of Object.entries(value)) { + const property = getProperty(preTransformedKey); + if (property != null) { + missingRequiredKeys.delete(preTransformedKey); + const value = yield property.transform(preTransformedItemValue); + if (value.ok) { + transformed[property.transformedKey] = value.value; + } + else { + transformed[preTransformedKey] = preTransformedItemValue; + errors.push(...value.errors); + } + } + else { + switch (unrecognizedObjectKeys) { + case \\"fail\\": + errors.push({ + path: [...breadcrumbsPrefix, preTransformedKey], + message: \`Unexpected key \\"\${preTransformedKey}\\"\`, + }); + break; + case \\"strip\\": + break; + case \\"passthrough\\": + transformed[preTransformedKey] = preTransformedItemValue; + break; + } + } + } + errors.push(...requiredKeys + .filter((key) => missingRequiredKeys.has(key)) + .map((key) => ({ + path: breadcrumbsPrefix, + message: \`Missing required key \\"\${key}\\"\`, + }))); + if (errors.length === 0 || skipValidation) { + return { + ok: true, + value: transformed, + }; + } + else { + return { + ok: false, + errors, + }; + } + }); +} +function getObjectUtils(schema) { + return { + extend: (extension) => { + const baseSchema = { + _getParsedProperties: () => __awaiter(this, void 0, void 0, function* () { + return [ + ...(yield schema._getParsedProperties()), + ...(yield extension._getParsedProperties()), + ]; + }), + _getRawProperties: () => __awaiter(this, void 0, void 0, function* () { + return [ + ...(yield schema._getRawProperties()), + ...(yield extension._getRawProperties()), + ]; + }), + parse: (raw, opts) => __awaiter(this, void 0, void 0, function* () { + return validateAndTransformExtendedObject({ + extensionKeys: yield extension._getRawProperties(), + value: raw, + transformBase: (rawBase) => schema.parse(rawBase, opts), + transformExtension: (rawExtension) => extension.parse(rawExtension, opts), + }); + }), + json: (parsed, opts) => __awaiter(this, void 0, void 0, function* () { + return validateAndTransformExtendedObject({ + extensionKeys: yield extension._getParsedProperties(), + value: parsed, + transformBase: (parsedBase) => schema.json(parsedBase, opts), + transformExtension: (parsedExtension) => extension.json(parsedExtension, opts), + }); + }), + getType: () => Schema_1.SchemaType.OBJECT, + }; + return Object.assign(Object.assign(Object.assign(Object.assign({}, baseSchema), (0, schema_utils_1.getSchemaUtils)(baseSchema)), (0, object_like_1.getObjectLikeUtils)(baseSchema)), getObjectUtils(baseSchema)); + }, + }; +} +exports.getObjectUtils = getObjectUtils; +function validateAndTransformExtendedObject({ extensionKeys, value, transformBase, transformExtension, }) { + return __awaiter(this, void 0, void 0, function* () { + const extensionPropertiesSet = new Set(extensionKeys); + const [extensionProperties, baseProperties] = (0, partition_1.partition)((0, keys_1.keys)(value), (key) => extensionPropertiesSet.has(key)); + const transformedBase = yield transformBase((0, filterObject_1.filterObject)(value, baseProperties)); + const transformedExtension = yield transformExtension((0, filterObject_1.filterObject)(value, extensionProperties)); + if (transformedBase.ok && transformedExtension.ok) { + return { + ok: true, + value: Object.assign(Object.assign({}, transformedBase.value), transformedExtension.value), + }; + } + else { + return { + ok: false, + errors: [ + ...(transformedBase.ok ? [] : transformedBase.errors), + ...(transformedExtension.ok ? [] : transformedExtension.errors), + ], + }; + } + }); +} +function isSchemaRequired(schema) { + return __awaiter(this, void 0, void 0, function* () { + return !(yield isSchemaOptional(schema)); + }); +} +function isSchemaOptional(schema) { + return __awaiter(this, void 0, void 0, function* () { + switch (yield schema.getType()) { + case Schema_1.SchemaType.ANY: + case Schema_1.SchemaType.UNKNOWN: + case Schema_1.SchemaType.OPTIONAL: + return true; + default: + return false; + } + }); +} +", + "name": "object.js", + "type": "file", + }, + Object { + "contents": "import { inferParsedPropertySchema, inferRawObjectFromPropertySchemas, ObjectSchema, PropertySchemas } from \\"./types\\"; +export declare function objectWithoutOptionalProperties>(schemas: T): inferObjectWithoutOptionalPropertiesSchemaFromPropertySchemas; +export declare type inferObjectWithoutOptionalPropertiesSchemaFromPropertySchemas> = ObjectSchema, inferParsedObjectWithoutOptionalPropertiesFromPropertySchemas>; +export declare type inferParsedObjectWithoutOptionalPropertiesFromPropertySchemas> = { + [K in keyof T]: inferParsedPropertySchema; +}; +", + "name": "objectWithoutOptionalProperties.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.objectWithoutOptionalProperties = void 0; +const object_1 = require(\\"./object\\"); +function objectWithoutOptionalProperties(schemas) { + return (0, object_1.object)(schemas); +} +exports.objectWithoutOptionalProperties = objectWithoutOptionalProperties; +", + "name": "objectWithoutOptionalProperties.js", + "type": "file", + }, + Object { + "contents": "import { Schema } from \\"../../Schema\\"; +export declare function property(rawKey: RawKey, valueSchema: Schema): Property; +export interface Property { + rawKey: RawKey; + valueSchema: Schema; + isProperty: true; +} +export declare function isProperty>(maybeProperty: unknown): maybeProperty is O; +", + "name": "property.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.isProperty = exports.property = void 0; +function property(rawKey, valueSchema) { + return { + rawKey, + valueSchema, + isProperty: true, + }; +} +exports.property = property; +function isProperty(maybeProperty) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + return maybeProperty.isProperty; +} +exports.isProperty = isProperty; +", + "name": "property.js", + "type": "file", + }, + Object { + "contents": "import { BaseSchema, inferParsed, inferRaw, Schema } from \\"../../Schema\\"; +import { addQuestionMarksToNullableProperties } from \\"../../utils/addQuestionMarksToNullableProperties\\"; +import { ObjectLikeUtils } from \\"../object-like\\"; +import { SchemaUtils } from \\"../schema-utils\\"; +import { Property } from \\"./property\\"; +export declare type ObjectSchema = BaseObjectSchema & ObjectLikeUtils & ObjectUtils & SchemaUtils; +export interface BaseObjectSchema extends BaseSchema { + _getRawProperties: () => Promise<(keyof Raw)[]>; + _getParsedProperties: () => Promise<(keyof Parsed)[]>; +} +export interface ObjectUtils { + extend: (schemas: ObjectSchema) => ObjectSchema; +} +export declare type inferRawObject> = O extends ObjectSchema ? Raw : never; +export declare type inferParsedObject> = O extends ObjectSchema ? Parsed : never; +export declare type inferObjectSchemaFromPropertySchemas> = ObjectSchema, inferParsedObjectFromPropertySchemas>; +export declare type inferRawObjectFromPropertySchemas> = addQuestionMarksToNullableProperties<{ + [ParsedKey in keyof T as inferRawKey]: inferRawPropertySchema; +}>; +export declare type inferParsedObjectFromPropertySchemas> = addQuestionMarksToNullableProperties<{ + [K in keyof T]: inferParsedPropertySchema; +}>; +export declare type PropertySchemas = Record | Schema>; +export declare type inferRawPropertySchema

| Schema> = P extends Property ? Raw : P extends Schema ? inferRaw

: never; +export declare type inferParsedPropertySchema

| Schema> = P extends Property ? Parsed : P extends Schema ? inferParsed

: never; +export declare type inferRawKey | Schema> = P extends Property ? Raw : ParsedKey; +", + "name": "types.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "types.js", + "type": "file", + }, + ], + "name": "object", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": "import { BaseSchema } from \\"../../Schema\\"; +import { ObjectLikeSchema, ObjectLikeUtils } from \\"./types\\"; +export declare function getObjectLikeUtils(schema: BaseSchema): ObjectLikeUtils; +/** + * object-like utils are defined in one file to resolve issues with circular imports + */ +export declare function withParsedProperties(objectLike: BaseSchema, properties: { + [K in keyof Properties]: Properties[K] | ((parsed: ParsedObjectShape) => Properties[K]); +}): ObjectLikeSchema; +", + "name": "getObjectLikeUtils.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.withParsedProperties = exports.getObjectLikeUtils = void 0; +const filterObject_1 = require(\\"../../utils/filterObject\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +const isPlainObject_1 = require(\\"../../utils/isPlainObject\\"); +const schema_utils_1 = require(\\"../schema-utils\\"); +function getObjectLikeUtils(schema) { + return { + withParsedProperties: (properties) => withParsedProperties(schema, properties), + }; +} +exports.getObjectLikeUtils = getObjectLikeUtils; +/** + * object-like utils are defined in one file to resolve issues with circular imports + */ +function withParsedProperties(objectLike, properties) { + const objectSchema = { + parse: (raw, opts) => __awaiter(this, void 0, void 0, function* () { + const parsedObject = yield objectLike.parse(raw, opts); + if (!parsedObject.ok) { + return parsedObject; + } + const additionalProperties = Object.entries(properties).reduce((processed, [key, value]) => { + return Object.assign(Object.assign({}, processed), { [key]: typeof value === \\"function\\" ? value(parsedObject.value) : value }); + }, {}); + return { + ok: true, + value: Object.assign(Object.assign({}, parsedObject.value), additionalProperties), + }; + }), + json: (parsed, opts) => { + var _a; + if (!(0, isPlainObject_1.isPlainObject)(parsed)) { + return { + ok: false, + errors: [ + { + path: (_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : [], + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(parsed, \\"object\\"), + }, + ], + }; + } + // strip out added properties + const addedPropertyKeys = new Set(Object.keys(properties)); + const parsedWithoutAddedProperties = (0, filterObject_1.filterObject)(parsed, Object.keys(parsed).filter((key) => !addedPropertyKeys.has(key))); + return objectLike.json(parsedWithoutAddedProperties, opts); + }, + getType: () => objectLike.getType(), + }; + return Object.assign(Object.assign(Object.assign({}, objectSchema), (0, schema_utils_1.getSchemaUtils)(objectSchema)), getObjectLikeUtils(objectSchema)); +} +exports.withParsedProperties = withParsedProperties; +", + "name": "getObjectLikeUtils.js", + "type": "file", + }, + Object { + "contents": "export { getObjectLikeUtils, withParsedProperties } from \\"./getObjectLikeUtils\\"; +export type { ObjectLikeSchema, ObjectLikeUtils } from \\"./types\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.withParsedProperties = exports.getObjectLikeUtils = void 0; +var getObjectLikeUtils_1 = require(\\"./getObjectLikeUtils\\"); +Object.defineProperty(exports, \\"getObjectLikeUtils\\", { enumerable: true, get: function () { return getObjectLikeUtils_1.getObjectLikeUtils; } }); +Object.defineProperty(exports, \\"withParsedProperties\\", { enumerable: true, get: function () { return getObjectLikeUtils_1.withParsedProperties; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": "import { BaseSchema, Schema } from \\"../../Schema\\"; +export declare type ObjectLikeSchema = Schema & BaseSchema & ObjectLikeUtils; +export interface ObjectLikeUtils { + withParsedProperties: >(properties: { + [K in keyof T]: T[K] | ((parsed: Parsed) => T[K]); + }) => ObjectLikeSchema; +} +", + "name": "types.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "types.js", + "type": "file", + }, + ], + "name": "object-like", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": "export declare const any: () => import(\\"../../Schema\\").Schema; +", + "name": "any.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.any = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const createIdentitySchemaCreator_1 = require(\\"../../utils/createIdentitySchemaCreator\\"); +exports.any = (0, createIdentitySchemaCreator_1.createIdentitySchemaCreator)(Schema_1.SchemaType.ANY, (value) => ({ ok: true, value })); +", + "name": "any.js", + "type": "file", + }, + Object { + "contents": "export declare const boolean: () => import(\\"../../Schema\\").Schema; +", + "name": "boolean.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.boolean = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const createIdentitySchemaCreator_1 = require(\\"../../utils/createIdentitySchemaCreator\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +exports.boolean = (0, createIdentitySchemaCreator_1.createIdentitySchemaCreator)(Schema_1.SchemaType.BOOLEAN, (value, { breadcrumbsPrefix = [] } = {}) => { + if (typeof value === \\"boolean\\") { + return { + ok: true, + value, + }; + } + else { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(value, \\"boolean\\"), + }, + ], + }; + } +}); +", + "name": "boolean.js", + "type": "file", + }, + Object { + "contents": "export { any } from \\"./any\\"; +export { boolean } from \\"./boolean\\"; +export { number } from \\"./number\\"; +export { string } from \\"./string\\"; +export { unknown } from \\"./unknown\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.unknown = exports.string = exports.number = exports.boolean = exports.any = void 0; +var any_1 = require(\\"./any\\"); +Object.defineProperty(exports, \\"any\\", { enumerable: true, get: function () { return any_1.any; } }); +var boolean_1 = require(\\"./boolean\\"); +Object.defineProperty(exports, \\"boolean\\", { enumerable: true, get: function () { return boolean_1.boolean; } }); +var number_1 = require(\\"./number\\"); +Object.defineProperty(exports, \\"number\\", { enumerable: true, get: function () { return number_1.number; } }); +var string_1 = require(\\"./string\\"); +Object.defineProperty(exports, \\"string\\", { enumerable: true, get: function () { return string_1.string; } }); +var unknown_1 = require(\\"./unknown\\"); +Object.defineProperty(exports, \\"unknown\\", { enumerable: true, get: function () { return unknown_1.unknown; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": "export declare const number: () => import(\\"../../Schema\\").Schema; +", + "name": "number.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.number = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const createIdentitySchemaCreator_1 = require(\\"../../utils/createIdentitySchemaCreator\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +exports.number = (0, createIdentitySchemaCreator_1.createIdentitySchemaCreator)(Schema_1.SchemaType.NUMBER, (value, { breadcrumbsPrefix = [] } = {}) => { + if (typeof value === \\"number\\") { + return { + ok: true, + value, + }; + } + else { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(value, \\"number\\"), + }, + ], + }; + } +}); +", + "name": "number.js", + "type": "file", + }, + Object { + "contents": "export declare const string: () => import(\\"../../Schema\\").Schema; +", + "name": "string.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.string = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const createIdentitySchemaCreator_1 = require(\\"../../utils/createIdentitySchemaCreator\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +exports.string = (0, createIdentitySchemaCreator_1.createIdentitySchemaCreator)(Schema_1.SchemaType.STRING, (value, { breadcrumbsPrefix = [] } = {}) => { + if (typeof value === \\"string\\") { + return { + ok: true, + value, + }; + } + else { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(value, \\"string\\"), + }, + ], + }; + } +}); +", + "name": "string.js", + "type": "file", + }, + Object { + "contents": "export declare const unknown: () => import(\\"../../Schema\\").Schema; +", + "name": "unknown.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.unknown = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const createIdentitySchemaCreator_1 = require(\\"../../utils/createIdentitySchemaCreator\\"); +exports.unknown = (0, createIdentitySchemaCreator_1.createIdentitySchemaCreator)(Schema_1.SchemaType.UNKNOWN, (value) => ({ ok: true, value })); +", + "name": "unknown.js", + "type": "file", + }, + ], + "name": "primitives", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": "export { record } from \\"./record\\"; +export type { BaseRecordSchema, RecordSchema } from \\"./types\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.record = void 0; +var record_1 = require(\\"./record\\"); +Object.defineProperty(exports, \\"record\\", { enumerable: true, get: function () { return record_1.record; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": "import { Schema } from \\"../../Schema\\"; +import { RecordSchema } from \\"./types\\"; +export declare function record(keySchema: Schema, valueSchema: Schema): RecordSchema; +", + "name": "record.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.record = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const entries_1 = require(\\"../../utils/entries\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +const isPlainObject_1 = require(\\"../../utils/isPlainObject\\"); +const maybeSkipValidation_1 = require(\\"../../utils/maybeSkipValidation\\"); +const schema_utils_1 = require(\\"../schema-utils\\"); +function record(keySchema, valueSchema) { + const baseSchema = { + parse: (raw, opts) => __awaiter(this, void 0, void 0, function* () { + return validateAndTransformRecord({ + value: raw, + isKeyNumeric: (yield keySchema.getType()) === Schema_1.SchemaType.NUMBER, + transformKey: (key) => { + var _a; + return keySchema.parse(key, Object.assign(Object.assign({}, opts), { breadcrumbsPrefix: [...((_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : []), \`\${key} (key)\`] })); + }, + transformValue: (value, key) => { + var _a; + return valueSchema.parse(value, Object.assign(Object.assign({}, opts), { breadcrumbsPrefix: [...((_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : []), \`\${key}\`] })); + }, + breadcrumbsPrefix: opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix, + }); + }), + json: (parsed, opts) => __awaiter(this, void 0, void 0, function* () { + return validateAndTransformRecord({ + value: parsed, + isKeyNumeric: (yield keySchema.getType()) === Schema_1.SchemaType.NUMBER, + transformKey: (key) => { + var _a; + return keySchema.json(key, Object.assign(Object.assign({}, opts), { breadcrumbsPrefix: [...((_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : []), \`\${key} (key)\`] })); + }, + transformValue: (value, key) => { + var _a; + return valueSchema.json(value, Object.assign(Object.assign({}, opts), { breadcrumbsPrefix: [...((_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : []), \`\${key}\`] })); + }, + breadcrumbsPrefix: opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix, + }); + }), + getType: () => Schema_1.SchemaType.RECORD, + }; + return Object.assign(Object.assign({}, (0, maybeSkipValidation_1.maybeSkipValidation)(baseSchema)), (0, schema_utils_1.getSchemaUtils)(baseSchema)); +} +exports.record = record; +function validateAndTransformRecord({ value, isKeyNumeric, transformKey, transformValue, breadcrumbsPrefix = [], }) { + return __awaiter(this, void 0, void 0, function* () { + if (!(0, isPlainObject_1.isPlainObject)(value)) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(value, \\"object\\"), + }, + ], + }; + } + return (0, entries_1.entries)(value).reduce((accPromise, [stringKey, value]) => __awaiter(this, void 0, void 0, function* () { + // skip nullish keys + if (value == null) { + return accPromise; + } + const acc = yield accPromise; + let key = stringKey; + if (isKeyNumeric) { + const numberKey = stringKey.length > 0 ? Number(stringKey) : NaN; + if (!isNaN(numberKey)) { + key = numberKey; + } + } + const transformedKey = yield transformKey(key); + const transformedValue = yield transformValue(value, key); + if (acc.ok && transformedKey.ok && transformedValue.ok) { + return { + ok: true, + value: Object.assign(Object.assign({}, acc.value), { [transformedKey.value]: transformedValue.value }), + }; + } + const errors = []; + if (!acc.ok) { + errors.push(...acc.errors); + } + if (!transformedKey.ok) { + errors.push(...transformedKey.errors); + } + if (!transformedValue.ok) { + errors.push(...transformedValue.errors); + } + return { + ok: false, + errors, + }; + }), Promise.resolve({ ok: true, value: {} })); + }); +} +", + "name": "record.js", + "type": "file", + }, + Object { + "contents": "import { BaseSchema } from \\"../../Schema\\"; +import { SchemaUtils } from \\"../schema-utils\\"; +export declare type RecordSchema = BaseRecordSchema & SchemaUtils, Record>; +export declare type BaseRecordSchema = BaseSchema, Record>; +", + "name": "types.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "types.js", + "type": "file", + }, + ], + "name": "record", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": "import { ValidationError } from \\"../../Schema\\"; +export declare class JsonError extends Error { + readonly errors: ValidationError[]; + constructor(errors: ValidationError[]); +} +", + "name": "JsonError.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.JsonError = void 0; +const stringifyValidationErrors_1 = require(\\"./stringifyValidationErrors\\"); +class JsonError extends Error { + constructor(errors) { + super(errors.map(stringifyValidationErrors_1.stringifyValidationError).join(\\"; \\")); + this.errors = errors; + Object.setPrototypeOf(this, JsonError.prototype); + } +} +exports.JsonError = JsonError; +", + "name": "JsonError.js", + "type": "file", + }, + Object { + "contents": "import { ValidationError } from \\"../../Schema\\"; +export declare class ParseError extends Error { + readonly errors: ValidationError[]; + constructor(errors: ValidationError[]); +} +", + "name": "ParseError.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.ParseError = void 0; +const stringifyValidationErrors_1 = require(\\"./stringifyValidationErrors\\"); +class ParseError extends Error { + constructor(errors) { + super(errors.map(stringifyValidationErrors_1.stringifyValidationError).join(\\"; \\")); + this.errors = errors; + Object.setPrototypeOf(this, ParseError.prototype); + } +} +exports.ParseError = ParseError; +", + "name": "ParseError.js", + "type": "file", + }, + Object { + "contents": "import { BaseSchema, Schema, SchemaOptions } from \\"../../Schema\\"; +export interface SchemaUtils { + optional: () => Schema; + transform: (transformer: SchemaTransformer) => Schema; + parseOrThrow: (raw: unknown, opts?: SchemaOptions) => Promise; + jsonOrThrow: (raw: unknown, opts?: SchemaOptions) => Promise; +} +export interface SchemaTransformer { + transform: (parsed: Parsed) => Transformed; + untransform: (transformed: any) => Parsed; +} +export declare function getSchemaUtils(schema: BaseSchema): SchemaUtils; +/** + * schema utils are defined in one file to resolve issues with circular imports + */ +export declare function optional(schema: BaseSchema): Schema; +export declare function transform(schema: BaseSchema, transformer: SchemaTransformer): Schema; +", + "name": "getSchemaUtils.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.transform = exports.optional = exports.getSchemaUtils = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const JsonError_1 = require(\\"./JsonError\\"); +const ParseError_1 = require(\\"./ParseError\\"); +function getSchemaUtils(schema) { + return { + optional: () => optional(schema), + transform: (transformer) => transform(schema, transformer), + parseOrThrow: (raw, opts) => __awaiter(this, void 0, void 0, function* () { + const parsed = yield schema.parse(raw, opts); + if (parsed.ok) { + return parsed.value; + } + throw new ParseError_1.ParseError(parsed.errors); + }), + jsonOrThrow: (parsed, opts) => __awaiter(this, void 0, void 0, function* () { + const raw = yield schema.json(parsed, opts); + if (raw.ok) { + return raw.value; + } + throw new JsonError_1.JsonError(raw.errors); + }), + }; +} +exports.getSchemaUtils = getSchemaUtils; +/** + * schema utils are defined in one file to resolve issues with circular imports + */ +function optional(schema) { + const baseSchema = { + parse: (raw, opts) => { + if (raw == null) { + return { + ok: true, + value: undefined, + }; + } + return schema.parse(raw, opts); + }, + json: (parsed, opts) => { + if (parsed == null) { + return { + ok: true, + value: null, + }; + } + return schema.json(parsed, opts); + }, + getType: () => Schema_1.SchemaType.OPTIONAL, + }; + return Object.assign(Object.assign({}, baseSchema), getSchemaUtils(baseSchema)); +} +exports.optional = optional; +function transform(schema, transformer) { + const baseSchema = { + parse: (raw, opts) => __awaiter(this, void 0, void 0, function* () { + const parsed = yield schema.parse(raw, opts); + if (!parsed.ok) { + return parsed; + } + return { + ok: true, + value: transformer.transform(parsed.value), + }; + }), + json: (transformed, opts) => __awaiter(this, void 0, void 0, function* () { + const parsed = yield transformer.untransform(transformed); + return schema.json(parsed, opts); + }), + getType: () => schema.getType(), + }; + return Object.assign(Object.assign({}, baseSchema), getSchemaUtils(baseSchema)); +} +exports.transform = transform; +", + "name": "getSchemaUtils.js", + "type": "file", + }, + Object { + "contents": "export { getSchemaUtils, optional, transform } from \\"./getSchemaUtils\\"; +export type { SchemaUtils } from \\"./getSchemaUtils\\"; +export { JsonError } from \\"./JsonError\\"; +export { ParseError } from \\"./ParseError\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.ParseError = exports.JsonError = exports.transform = exports.optional = exports.getSchemaUtils = void 0; +var getSchemaUtils_1 = require(\\"./getSchemaUtils\\"); +Object.defineProperty(exports, \\"getSchemaUtils\\", { enumerable: true, get: function () { return getSchemaUtils_1.getSchemaUtils; } }); +Object.defineProperty(exports, \\"optional\\", { enumerable: true, get: function () { return getSchemaUtils_1.optional; } }); +Object.defineProperty(exports, \\"transform\\", { enumerable: true, get: function () { return getSchemaUtils_1.transform; } }); +var JsonError_1 = require(\\"./JsonError\\"); +Object.defineProperty(exports, \\"JsonError\\", { enumerable: true, get: function () { return JsonError_1.JsonError; } }); +var ParseError_1 = require(\\"./ParseError\\"); +Object.defineProperty(exports, \\"ParseError\\", { enumerable: true, get: function () { return ParseError_1.ParseError; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": "import { ValidationError } from \\"../../Schema\\"; +export declare function stringifyValidationError(error: ValidationError): string; +", + "name": "stringifyValidationErrors.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.stringifyValidationError = void 0; +function stringifyValidationError(error) { + if (error.path.length === 0) { + return error.message; + } + return \`\${error.path.join(\\" -> \\")}: \${error.message}\`; +} +exports.stringifyValidationError = stringifyValidationError; +", + "name": "stringifyValidationErrors.js", + "type": "file", + }, + ], + "name": "schema-utils", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": "export { set } from \\"./set\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.set = void 0; +var set_1 = require(\\"./set\\"); +Object.defineProperty(exports, \\"set\\", { enumerable: true, get: function () { return set_1.set; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": "import { Schema } from \\"../../Schema\\"; +export declare function set(schema: Schema): Schema>; +", + "name": "set.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.set = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +const maybeSkipValidation_1 = require(\\"../../utils/maybeSkipValidation\\"); +const list_1 = require(\\"../list\\"); +const schema_utils_1 = require(\\"../schema-utils\\"); +function set(schema) { + const listSchema = (0, list_1.list)(schema); + const baseSchema = { + parse: (raw, opts) => __awaiter(this, void 0, void 0, function* () { + const parsedList = yield listSchema.parse(raw, opts); + if (parsedList.ok) { + return { + ok: true, + value: new Set(parsedList.value), + }; + } + else { + return parsedList; + } + }), + json: (parsed, opts) => __awaiter(this, void 0, void 0, function* () { + var _a; + if (!(parsed instanceof Set)) { + return { + ok: false, + errors: [ + { + path: (_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : [], + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(parsed, \\"Set\\"), + }, + ], + }; + } + const jsonList = yield listSchema.json([...parsed], opts); + return jsonList; + }), + getType: () => Schema_1.SchemaType.SET, + }; + return Object.assign(Object.assign({}, (0, maybeSkipValidation_1.maybeSkipValidation)(baseSchema)), (0, schema_utils_1.getSchemaUtils)(baseSchema)); +} +exports.set = set; +", + "name": "set.js", + "type": "file", + }, + ], + "name": "set", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": "export type { inferParsedUnidiscriminatedUnionSchema, inferRawUnidiscriminatedUnionSchema, UndiscriminatedUnionSchema, } from \\"./types\\"; +export { undiscriminatedUnion } from \\"./undiscriminatedUnion\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.undiscriminatedUnion = void 0; +var undiscriminatedUnion_1 = require(\\"./undiscriminatedUnion\\"); +Object.defineProperty(exports, \\"undiscriminatedUnion\\", { enumerable: true, get: function () { return undiscriminatedUnion_1.undiscriminatedUnion; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": "import { inferParsed, inferRaw, Schema } from \\"../../Schema\\"; +export declare type UndiscriminatedUnionSchema = Schema, inferParsedUnidiscriminatedUnionSchema>; +export declare type inferRawUnidiscriminatedUnionSchema = inferRaw; +export declare type inferParsedUnidiscriminatedUnionSchema = inferParsed; +", + "name": "types.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "types.js", + "type": "file", + }, + Object { + "contents": "import { Schema } from \\"../../Schema\\"; +import { inferParsedUnidiscriminatedUnionSchema, inferRawUnidiscriminatedUnionSchema } from \\"./types\\"; +export declare function undiscriminatedUnion, ...Schema[]]>(schemas: Schemas): Schema, inferParsedUnidiscriminatedUnionSchema>; +", + "name": "undiscriminatedUnion.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.undiscriminatedUnion = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const maybeSkipValidation_1 = require(\\"../../utils/maybeSkipValidation\\"); +const schema_utils_1 = require(\\"../schema-utils\\"); +function undiscriminatedUnion(schemas) { + const baseSchema = { + parse: (raw, opts) => __awaiter(this, void 0, void 0, function* () { + return validateAndTransformUndiscriminatedUnion((schema, opts) => schema.parse(raw, opts), schemas, opts); + }), + json: (parsed, opts) => __awaiter(this, void 0, void 0, function* () { + return validateAndTransformUndiscriminatedUnion((schema, opts) => schema.json(parsed, opts), schemas, opts); + }), + getType: () => Schema_1.SchemaType.UNDISCRIMINATED_UNION, + }; + return Object.assign(Object.assign({}, (0, maybeSkipValidation_1.maybeSkipValidation)(baseSchema)), (0, schema_utils_1.getSchemaUtils)(baseSchema)); +} +exports.undiscriminatedUnion = undiscriminatedUnion; +function validateAndTransformUndiscriminatedUnion(transform, schemas, opts) { + return __awaiter(this, void 0, void 0, function* () { + const errors = []; + for (const [index, schema] of schemas.entries()) { + const transformed = yield transform(schema, Object.assign(Object.assign({}, opts), { skipValidation: false })); + if (transformed.ok) { + return transformed; + } + else { + for (const error of transformed.errors) { + errors.push({ + path: error.path, + message: \`[Variant \${index}] \${error.message}\`, + }); + } + } + } + return { + ok: false, + errors, + }; + }); +} +", + "name": "undiscriminatedUnion.js", + "type": "file", + }, + ], + "name": "undiscriminated-union", + "type": "directory", + }, + Object { + "contents": Array [ + Object { + "contents": "export declare function discriminant(parsedDiscriminant: ParsedDiscriminant, rawDiscriminant: RawDiscriminant): Discriminant; +export interface Discriminant { + parsedDiscriminant: ParsedDiscriminant; + rawDiscriminant: RawDiscriminant; +} +", + "name": "discriminant.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.discriminant = void 0; +function discriminant(parsedDiscriminant, rawDiscriminant) { + return { + parsedDiscriminant, + rawDiscriminant, + }; +} +exports.discriminant = discriminant; +", + "name": "discriminant.js", + "type": "file", + }, + Object { + "contents": "export { discriminant } from \\"./discriminant\\"; +export type { Discriminant } from \\"./discriminant\\"; +export type { inferParsedDiscriminant, inferParsedUnion, inferRawDiscriminant, inferRawUnion, UnionSubtypes, } from \\"./types\\"; +export { union } from \\"./union\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.union = exports.discriminant = void 0; +var discriminant_1 = require(\\"./discriminant\\"); +Object.defineProperty(exports, \\"discriminant\\", { enumerable: true, get: function () { return discriminant_1.discriminant; } }); +var union_1 = require(\\"./union\\"); +Object.defineProperty(exports, \\"union\\", { enumerable: true, get: function () { return union_1.union; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": "import { inferParsedObject, inferRawObject, ObjectSchema } from \\"../object\\"; +import { Discriminant } from \\"./discriminant\\"; +export declare type UnionSubtypes = { + [K in DiscriminantValues]: ObjectSchema; +}; +export declare type inferRawUnion, U extends UnionSubtypes> = { + [K in keyof U]: Record, K> & inferRawObject; +}[keyof U]; +export declare type inferParsedUnion, U extends UnionSubtypes> = { + [K in keyof U]: Record, K> & inferParsedObject; +}[keyof U]; +export declare type inferRawDiscriminant> = D extends string ? D : D extends Discriminant ? Raw : never; +export declare type inferParsedDiscriminant> = D extends string ? D : D extends Discriminant ? Parsed : never; +", + "name": "types.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "types.js", + "type": "file", + }, + Object { + "contents": "import { ObjectLikeSchema } from \\"../object-like\\"; +import { Discriminant } from \\"./discriminant\\"; +import { inferParsedUnion, inferRawUnion, UnionSubtypes } from \\"./types\\"; +export declare function union, U extends UnionSubtypes>(discriminant: D, union: U): ObjectLikeSchema, inferParsedUnion>; +", + "name": "union.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === \\"function\\") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.union = void 0; +const Schema_1 = require(\\"../../Schema\\"); +const getErrorMessageForIncorrectType_1 = require(\\"../../utils/getErrorMessageForIncorrectType\\"); +const isPlainObject_1 = require(\\"../../utils/isPlainObject\\"); +const keys_1 = require(\\"../../utils/keys\\"); +const maybeSkipValidation_1 = require(\\"../../utils/maybeSkipValidation\\"); +const enum_1 = require(\\"../enum\\"); +const object_like_1 = require(\\"../object-like\\"); +const schema_utils_1 = require(\\"../schema-utils\\"); +function union(discriminant, union) { + const rawDiscriminant = typeof discriminant === \\"string\\" ? discriminant : discriminant.rawDiscriminant; + const parsedDiscriminant = typeof discriminant === \\"string\\" + ? discriminant + : discriminant.parsedDiscriminant; + const discriminantValueSchema = (0, enum_1.enum_)((0, keys_1.keys)(union)); + const baseSchema = { + parse: (raw, opts) => __awaiter(this, void 0, void 0, function* () { + return transformAndValidateUnion({ + value: raw, + discriminant: rawDiscriminant, + transformedDiscriminant: parsedDiscriminant, + transformDiscriminantValue: (discriminantValue) => { + var _a; + return discriminantValueSchema.parse(discriminantValue, { + allowUnrecognizedEnumValues: opts === null || opts === void 0 ? void 0 : opts.allowUnrecognizedUnionMembers, + breadcrumbsPrefix: [...((_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : []), rawDiscriminant], + }); + }, + getAdditionalPropertiesSchema: (discriminantValue) => union[discriminantValue], + allowUnrecognizedUnionMembers: opts === null || opts === void 0 ? void 0 : opts.allowUnrecognizedUnionMembers, + transformAdditionalProperties: (additionalProperties, additionalPropertiesSchema) => additionalPropertiesSchema.parse(additionalProperties, opts), + breadcrumbsPrefix: opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix, + }); + }), + json: (parsed, opts) => __awaiter(this, void 0, void 0, function* () { + return transformAndValidateUnion({ + value: parsed, + discriminant: parsedDiscriminant, + transformedDiscriminant: rawDiscriminant, + transformDiscriminantValue: (discriminantValue) => { + var _a; + return discriminantValueSchema.json(discriminantValue, { + allowUnrecognizedEnumValues: opts === null || opts === void 0 ? void 0 : opts.allowUnrecognizedUnionMembers, + breadcrumbsPrefix: [...((_a = opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix) !== null && _a !== void 0 ? _a : []), parsedDiscriminant], + }); + }, + getAdditionalPropertiesSchema: (discriminantValue) => union[discriminantValue], + allowUnrecognizedUnionMembers: opts === null || opts === void 0 ? void 0 : opts.allowUnrecognizedUnionMembers, + transformAdditionalProperties: (additionalProperties, additionalPropertiesSchema) => additionalPropertiesSchema.json(additionalProperties, opts), + breadcrumbsPrefix: opts === null || opts === void 0 ? void 0 : opts.breadcrumbsPrefix, + }); + }), + getType: () => Schema_1.SchemaType.UNION, + }; + return Object.assign(Object.assign(Object.assign({}, (0, maybeSkipValidation_1.maybeSkipValidation)(baseSchema)), (0, schema_utils_1.getSchemaUtils)(baseSchema)), (0, object_like_1.getObjectLikeUtils)(baseSchema)); +} +exports.union = union; +function transformAndValidateUnion({ value, discriminant, transformedDiscriminant, transformDiscriminantValue, getAdditionalPropertiesSchema, allowUnrecognizedUnionMembers = false, transformAdditionalProperties, breadcrumbsPrefix = [], }) { + return __awaiter(this, void 0, void 0, function* () { + if (!(0, isPlainObject_1.isPlainObject)(value)) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: (0, getErrorMessageForIncorrectType_1.getErrorMessageForIncorrectType)(value, \\"object\\"), + }, + ], + }; + } + const _a = value, _b = discriminant, discriminantValue = _a[_b], additionalProperties = __rest(_a, [typeof _b === \\"symbol\\" ? _b : _b + \\"\\"]); + if (discriminantValue == null) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: \`Missing discriminant (\\"\${discriminant}\\")\`, + }, + ], + }; + } + const transformedDiscriminantValue = yield transformDiscriminantValue(discriminantValue); + if (!transformedDiscriminantValue.ok) { + return { + ok: false, + errors: transformedDiscriminantValue.errors, + }; + } + const additionalPropertiesSchema = getAdditionalPropertiesSchema(transformedDiscriminantValue.value); + if (additionalPropertiesSchema == null) { + if (allowUnrecognizedUnionMembers) { + return { + ok: true, + value: Object.assign({ [transformedDiscriminant]: transformedDiscriminantValue.value }, additionalProperties), + }; + } + else { + return { + ok: false, + errors: [ + { + path: [...breadcrumbsPrefix, discriminant], + message: \\"Unexpected discriminant value\\", + }, + ], + }; + } + } + const transformedAdditionalProperties = yield transformAdditionalProperties(additionalProperties, additionalPropertiesSchema); + if (!transformedAdditionalProperties.ok) { + return transformedAdditionalProperties; + } + return { + ok: true, + value: Object.assign({ [transformedDiscriminant]: discriminantValue }, transformedAdditionalProperties.value), + }; + }); +} +", + "name": "union.js", + "type": "file", + }, + ], + "name": "union", + "type": "directory", + }, + ], + "name": "builders", + "type": "directory", + }, + Object { + "contents": "export * from \\"./builders\\"; +export type { inferParsed, inferRaw, Schema, SchemaOptions } from \\"./Schema\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +__exportStar(require(\\"./builders\\"), exports); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": "export declare type MaybePromise = T | Promise; +", + "name": "MaybePromise.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "MaybePromise.js", + "type": "file", + }, + Object { + "contents": "export declare type addQuestionMarksToNullableProperties = { + [K in OptionalKeys]?: T[K]; +} & Pick>; +export declare type OptionalKeys = { + [K in keyof T]-?: undefined extends T[K] ? K : null extends T[K] ? K : 1 extends (any extends T[K] ? 0 : 1) ? never : K; +}[keyof T]; +export declare type RequiredKeys = Exclude>; +", + "name": "addQuestionMarksToNullableProperties.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +", + "name": "addQuestionMarksToNullableProperties.js", + "type": "file", + }, + Object { + "contents": "import { MaybeValid, Schema, SchemaOptions, SchemaType } from \\"../Schema\\"; +export declare function createIdentitySchemaCreator(schemaType: SchemaType, validate: (value: unknown, opts?: SchemaOptions) => MaybeValid): () => Schema; +", + "name": "createIdentitySchemaCreator.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.createIdentitySchemaCreator = void 0; +const schema_utils_1 = require(\\"../builders/schema-utils\\"); +const maybeSkipValidation_1 = require(\\"./maybeSkipValidation\\"); +function createIdentitySchemaCreator(schemaType, validate) { + return () => { + const baseSchema = { + parse: validate, + json: validate, + getType: () => schemaType, + }; + return Object.assign(Object.assign({}, (0, maybeSkipValidation_1.maybeSkipValidation)(baseSchema)), (0, schema_utils_1.getSchemaUtils)(baseSchema)); + }; +} +exports.createIdentitySchemaCreator = createIdentitySchemaCreator; +", + "name": "createIdentitySchemaCreator.js", + "type": "file", + }, + Object { + "contents": "export declare function entries(object: T): [keyof T, T[keyof T]][]; +", + "name": "entries.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.entries = void 0; +function entries(object) { + return Object.entries(object); +} +exports.entries = entries; +", + "name": "entries.js", + "type": "file", + }, + Object { + "contents": "export declare function filterObject(obj: T, keysToInclude: K[]): Pick; +", + "name": "filterObject.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.filterObject = void 0; +function filterObject(obj, keysToInclude) { + const keysToIncludeSet = new Set(keysToInclude); + return Object.entries(obj).reduce((acc, [key, value]) => { + if (keysToIncludeSet.has(key)) { + acc[key] = value; + } + return acc; + // eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter + }, {}); +} +exports.filterObject = filterObject; +", + "name": "filterObject.js", + "type": "file", + }, + Object { + "contents": "export declare function getErrorMessageForIncorrectType(value: unknown, expectedType: string): string; +", + "name": "getErrorMessageForIncorrectType.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.getErrorMessageForIncorrectType = void 0; +function getErrorMessageForIncorrectType(value, expectedType) { + return \`Expected \${expectedType}. Received \${getTypeAsString(value)}.\`; +} +exports.getErrorMessageForIncorrectType = getErrorMessageForIncorrectType; +function getTypeAsString(value) { + if (Array.isArray(value)) { + return \\"list\\"; + } + if (value === null) { + return \\"null\\"; + } + switch (typeof value) { + case \\"string\\": + return \`\\"\${value}\\"\`; + case \\"number\\": + case \\"boolean\\": + case \\"undefined\\": + return \`\${value}\`; + } + return typeof value; +} +", + "name": "getErrorMessageForIncorrectType.js", + "type": "file", + }, + Object { + "contents": "export declare function isPlainObject(value: unknown): value is Record; +", + "name": "isPlainObject.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.isPlainObject = void 0; +// borrowed from https://github.com/lodash/lodash/blob/master/isPlainObject.js +function isPlainObject(value) { + if (typeof value !== \\"object\\" || value === null) { + return false; + } + if (Object.getPrototypeOf(value) === null) { + return true; + } + let proto = value; + while (Object.getPrototypeOf(proto) !== null) { + proto = Object.getPrototypeOf(proto); + } + return Object.getPrototypeOf(value) === proto; +} +exports.isPlainObject = isPlainObject; +", + "name": "isPlainObject.js", + "type": "file", + }, + Object { + "contents": "export declare function keys(object: T): (keyof T)[]; +", + "name": "keys.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.keys = void 0; +function keys(object) { + return Object.keys(object); +} +exports.keys = keys; +", + "name": "keys.js", + "type": "file", + }, + Object { + "contents": "import { BaseSchema } from \\"../Schema\\"; +export declare function maybeSkipValidation, Raw, Parsed>(schema: S): S; +", + "name": "maybeSkipValidation.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator[\\"throw\\"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.maybeSkipValidation = void 0; +function maybeSkipValidation(schema) { + return Object.assign(Object.assign({}, schema), { json: transformAndMaybeSkipValidation(schema.json), parse: transformAndMaybeSkipValidation(schema.parse) }); +} +exports.maybeSkipValidation = maybeSkipValidation; +function transformAndMaybeSkipValidation(transform) { + return (value, opts) => __awaiter(this, void 0, void 0, function* () { + const transformed = yield transform(value, opts); + const { skipValidation = false } = opts !== null && opts !== void 0 ? opts : {}; + if (!transformed.ok && skipValidation) { + // eslint-disable-next-line no-console + console.warn([ + \\"Failed to validate.\\", + ...transformed.errors.map((error) => \\" - \\" + + (error.path.length > 0 ? \`\${error.path.join(\\".\\")}: \${error.message}\` : error.message)), + ].join(\\"\\\\n\\")); + return { + ok: true, + value: value, + }; + } + else { + return transformed; + } + }); +} +", + "name": "maybeSkipValidation.js", + "type": "file", + }, + Object { + "contents": "export declare function partition(items: readonly T[], predicate: (item: T) => boolean): [T[], T[]]; +", + "name": "partition.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.partition = void 0; +function partition(items, predicate) { + const trueItems = [], falseItems = []; + for (const item of items) { + if (predicate(item)) { + trueItems.push(item); + } + else { + falseItems.push(item); + } + } + return [trueItems, falseItems]; +} +exports.partition = partition; +", + "name": "partition.js", + "type": "file", + }, + ], + "name": "utils", + "type": "directory", + }, + ], + "name": "schemas", + "type": "directory", + }, + ], + "name": "core", + "type": "directory", + }, + Object { + "contents": "export * as FernApi from \\"./api\\"; +export { FernApiClient } from \\"./Client\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, \\"default\\", { enumerable: true, value: v }); +}) : function(o, v) { + o[\\"default\\"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== \\"default\\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.FernApiClient = exports.FernApi = void 0; +exports.FernApi = __importStar(require(\\"./api\\")); +var Client_1 = require(\\"./Client\\"); +Object.defineProperty(exports, \\"FernApiClient\\", { enumerable: true, get: function () { return Client_1.FernApiClient; } }); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": "export * from \\"./resources\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +__exportStar(require(\\"./resources\\"), exports); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": "export * as package_ from \\"./package\\"; +export * from \\"./package/types\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, \\"default\\", { enumerable: true, value: v }); +}) : function(o, v) { + o[\\"default\\"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== \\"default\\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.package_ = void 0; +exports.package_ = __importStar(require(\\"./package\\")); +__exportStar(require(\\"./package/types\\"), exports); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": "export * from \\"./types\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +__exportStar(require(\\"./types\\"), exports); +", + "name": "index.js", + "type": "file", + }, + Object { + "contents": Array [ + Object { + "contents": "/** + * This file was auto-generated by Fern from our API Definition. + */ +import * as serializers from \\"../../..\\"; +import * as FernApi from \\"../../../../api\\"; +import * as core from \\"../../../../core\\"; +export declare const Package: core.serialization.ObjectSchema; +export declare namespace Package { + interface Raw { + name: string; + } +} +", + "name": "Package.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +/** + * This file was auto-generated by Fern from our API Definition. + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, \\"default\\", { enumerable: true, value: v }); +}) : function(o, v) { + o[\\"default\\"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== \\"default\\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.Package = void 0; +const core = __importStar(require(\\"../../../../core\\")); +exports.Package = core.serialization.object({ + name: core.serialization.string(), +}); +", + "name": "Package.js", + "type": "file", + }, + Object { + "contents": "/** + * This file was auto-generated by Fern from our API Definition. + */ +import * as serializers from \\"../../..\\"; +import * as FernApi from \\"../../../../api\\"; +import * as core from \\"../../../../core\\"; +export declare const Record_: core.serialization.ObjectSchema; +export declare namespace Record_ { + interface Raw { + foo: Record; + \\"3d\\": number; + } +} +", + "name": "Record_.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +/** + * This file was auto-generated by Fern from our API Definition. + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, \\"default\\", { enumerable: true, value: v }); +}) : function(o, v) { + o[\\"default\\"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== \\"default\\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +exports.Record_ = void 0; +const core = __importStar(require(\\"../../../../core\\")); +exports.Record_ = core.serialization.object({ + foo: core.serialization.record(core.serialization.string(), core.serialization.string()), + \\"3D\\": core.serialization.property(\\"3d\\", core.serialization.number()), +}); +", + "name": "Record_.js", + "type": "file", + }, + Object { + "contents": "export * from \\"./Package\\"; +export * from \\"./Record_\\"; +", + "name": "index.d.ts", + "type": "file", + }, + Object { + "contents": "\\"use strict\\"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || (\\"get\\" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== \\"default\\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, \\"__esModule\\", { value: true }); +__exportStar(require(\\"./Package\\"), exports); +__exportStar(require(\\"./Record_\\"), exports); +", + "name": "index.js", + "type": "file", + }, + ], + "name": "types", + "type": "directory", + }, + ], + "name": "package", + "type": "directory", + }, + ], + "name": "resources", + "type": "directory", + }, + ], + "name": "serialization", + "type": "directory", + }, +] +`; diff --git a/seed/pydantic-v2/reserved-keywords/resources/package/types/package.py b/seed/pydantic-v2/reserved-keywords/resources/package/types/package.py new file mode 100644 index 00000000000..1223115d21c --- /dev/null +++ b/seed/pydantic-v2/reserved-keywords/resources/package/types/package.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Package(BaseModel): + name: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/reserved-keywords/resources/package/types/record.py b/seed/pydantic-v2/reserved-keywords/resources/package/types/record.py new file mode 100644 index 00000000000..93e110c1d4c --- /dev/null +++ b/seed/pydantic-v2/reserved-keywords/resources/package/types/record.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Dict +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Record(BaseModel): + foo: Dict[str, str] + _3_d: int + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/reserved-keywords/snippet-templates.json b/seed/pydantic-v2/reserved-keywords/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/reserved-keywords/snippet.json b/seed/pydantic-v2/reserved-keywords/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/response-property/.mock/definition/__package__.yml b/seed/pydantic-v2/response-property/.mock/definition/__package__.yml new file mode 100644 index 00000000000..708a5a1139d --- /dev/null +++ b/seed/pydantic-v2/response-property/.mock/definition/__package__.yml @@ -0,0 +1,10 @@ +types: + StringResponse: + properties: + data: string + + OptionalStringResponse: optional + + WithMetadata: + properties: + metadata: map diff --git a/seed/pydantic-v2/response-property/.mock/definition/api.yml b/seed/pydantic-v2/response-property/.mock/definition/api.yml new file mode 100644 index 00000000000..4a1bb4a3045 --- /dev/null +++ b/seed/pydantic-v2/response-property/.mock/definition/api.yml @@ -0,0 +1 @@ +name: response-property diff --git a/seed/pydantic-v2/response-property/.mock/definition/service.yml b/seed/pydantic-v2/response-property/.mock/definition/service.yml new file mode 100644 index 00000000000..15de6ab767f --- /dev/null +++ b/seed/pydantic-v2/response-property/.mock/definition/service.yml @@ -0,0 +1,81 @@ +imports: + root: __package__.yml + +types: + WithDocs: + properties: + docs: string + + OptionalWithDocs: optional + + Movie: + properties: + id: string + name: string + + Response: + extends: + - root.WithMetadata + - WithDocs + properties: + data: Movie + +service: + auth: false + base-path: "" + endpoints: + getMovie: + method: POST + path: /movie + request: string + response: + type: Response + property: data + + getMovieDocs: + method: POST + path: /movie + request: string + response: + type: Response + property: docs + + getMovieName: + method: POST + path: /movie + request: string + response: + type: root.StringResponse + property: data + + getMovieMetadata: + method: POST + path: /movie + request: string + response: + type: Response + property: metadata + + getOptionalMovie: + method: POST + path: /movie + request: string + response: + type: optional + property: data + + getOptionalMovieDocs: + method: POST + path: /movie + request: string + response: + type: OptionalWithDocs + property: docs + + getOptionalMovieName: + method: POST + path: /movie + request: string + response: + type: root.OptionalStringResponse + property: data diff --git a/seed/pydantic-v2/response-property/.mock/fern.config.json b/seed/pydantic-v2/response-property/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/response-property/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/response-property/.mock/generators.yml b/seed/pydantic-v2/response-property/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/response-property/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/response-property/resources/service/types/movie.py b/seed/pydantic-v2/response-property/resources/service/types/movie.py new file mode 100644 index 00000000000..b1806ef94cc --- /dev/null +++ b/seed/pydantic-v2/response-property/resources/service/types/movie.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Movie(BaseModel): + id: str + name: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/response-property/resources/service/types/optional_with_docs.py b/seed/pydantic-v2/response-property/resources/service/types/optional_with_docs.py new file mode 100644 index 00000000000..a8a0f9f2542 --- /dev/null +++ b/seed/pydantic-v2/response-property/resources/service/types/optional_with_docs.py @@ -0,0 +1,21 @@ +from pydantic import RootModel +from typing import Optional +from resources.service.types.with_docs import WithDocs +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class OptionalWithDocs(RootModel[Optional[WithDocs]]): + root: Optional[WithDocs] + + def get_as_with_docs() -> UUID: + return self.root + + @staticmethod + def from_with_docs(value: Optional[WithDocs]) -> OptionalWithDocs: + OptionalWithDocs(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/response-property/resources/service/types/response.py b/seed/pydantic-v2/response-property/resources/service/types/response.py new file mode 100644 index 00000000000..50225536f27 --- /dev/null +++ b/seed/pydantic-v2/response-property/resources/service/types/response.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel +from types.with_metadata import WithMetadata +from resources.service.types.with_docs import WithDocs +from resources.service.types.movie import Movie +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class Response(BaseModel, WithMetadata, WithDocs): + data: Movie + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/response-property/resources/service/types/with_docs.py b/seed/pydantic-v2/response-property/resources/service/types/with_docs.py new file mode 100644 index 00000000000..55d9de87abb --- /dev/null +++ b/seed/pydantic-v2/response-property/resources/service/types/with_docs.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class WithDocs(BaseModel): + docs: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/response-property/snippet-templates.json b/seed/pydantic-v2/response-property/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/response-property/snippet.json b/seed/pydantic-v2/response-property/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/response-property/types/optional_string_response.py b/seed/pydantic-v2/response-property/types/optional_string_response.py new file mode 100644 index 00000000000..4191594f14d --- /dev/null +++ b/seed/pydantic-v2/response-property/types/optional_string_response.py @@ -0,0 +1,21 @@ +from pydantic import RootModel +from typing import Optional +from .types.string_response import StringResponse +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class OptionalStringResponse(RootModel[Optional[StringResponse]]): + root: Optional[StringResponse] + + def get_as_string_response() -> UUID: + return self.root + + @staticmethod + def from_string_response(value: Optional[StringResponse]) -> OptionalStringResponse: + OptionalStringResponse(root=value) + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/response-property/types/string_response.py b/seed/pydantic-v2/response-property/types/string_response.py new file mode 100644 index 00000000000..4eb29ff8d54 --- /dev/null +++ b/seed/pydantic-v2/response-property/types/string_response.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class StringResponse(BaseModel): + data: str + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/response-property/types/with_metadata.py b/seed/pydantic-v2/response-property/types/with_metadata.py new file mode 100644 index 00000000000..48878a3d87d --- /dev/null +++ b/seed/pydantic-v2/response-property/types/with_metadata.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel +from typing import Dict +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class WithMetadata(BaseModel): + metadata: Dict[str, str] + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/seed.yml b/seed/pydantic-v2/seed.yml new file mode 100644 index 00000000000..30f68bb552e --- /dev/null +++ b/seed/pydantic-v2/seed.yml @@ -0,0 +1,11 @@ +irVersion: v53 +displayName: Pydantic Model +image: fernapi/fern-pydantic-model-v2 +test: + docker: + image: fernapi/fern-pydantic-model-v2:latest + command: pnpm --filter @fern-api/fern-pydantic-model dockerTagLatest + +language: python +generatorType: Model +defaultOutputMode: local_files diff --git a/seed/pydantic-v2/server-sent-event-examples/.mock/definition/api.yml b/seed/pydantic-v2/server-sent-event-examples/.mock/definition/api.yml new file mode 100644 index 00000000000..80e84c41785 --- /dev/null +++ b/seed/pydantic-v2/server-sent-event-examples/.mock/definition/api.yml @@ -0,0 +1 @@ +name: server-sent-events diff --git a/seed/pydantic-v2/server-sent-event-examples/.mock/definition/completions.yml b/seed/pydantic-v2/server-sent-event-examples/.mock/definition/completions.yml new file mode 100644 index 00000000000..09a88253331 --- /dev/null +++ b/seed/pydantic-v2/server-sent-event-examples/.mock/definition/completions.yml @@ -0,0 +1,36 @@ +types: + StreamedCompletion: + properties: + delta: string + tokens: optional + +service: + auth: false + base-path: "" + endpoints: + stream: + method: POST + path: /stream + request: + name: StreamCompletionRequest + body: + properties: + query: string + response-stream: + type: StreamedCompletion + format: sse + terminator: "[[DONE]]" + examples: + - name: "Stream completions" + request: + query: "foo" + response: + stream: + - event: discriminant-1 + data: + delta: "foo" + tokens: 1 + - event: discriminant-2 + data: + delta: "bar" + tokens: 2 diff --git a/seed/pydantic-v2/server-sent-event-examples/.mock/fern.config.json b/seed/pydantic-v2/server-sent-event-examples/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/server-sent-event-examples/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/server-sent-event-examples/.mock/generators.yml b/seed/pydantic-v2/server-sent-event-examples/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/server-sent-event-examples/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/server-sent-event-examples/resources/completions/types/streamed_completion.py b/seed/pydantic-v2/server-sent-event-examples/resources/completions/types/streamed_completion.py new file mode 100644 index 00000000000..eab550662ab --- /dev/null +++ b/seed/pydantic-v2/server-sent-event-examples/resources/completions/types/streamed_completion.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class StreamedCompletion(BaseModel): + delta: str + tokens: Optional[int] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/server-sent-event-examples/snippet-templates.json b/seed/pydantic-v2/server-sent-event-examples/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/server-sent-event-examples/snippet.json b/seed/pydantic-v2/server-sent-event-examples/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/server-sent-events/.mock/definition/api.yml b/seed/pydantic-v2/server-sent-events/.mock/definition/api.yml new file mode 100644 index 00000000000..80e84c41785 --- /dev/null +++ b/seed/pydantic-v2/server-sent-events/.mock/definition/api.yml @@ -0,0 +1 @@ +name: server-sent-events diff --git a/seed/pydantic-v2/server-sent-events/.mock/definition/completions.yml b/seed/pydantic-v2/server-sent-events/.mock/definition/completions.yml new file mode 100644 index 00000000000..d1748fad19e --- /dev/null +++ b/seed/pydantic-v2/server-sent-events/.mock/definition/completions.yml @@ -0,0 +1,22 @@ +types: + StreamedCompletion: + properties: + delta: string + tokens: optional + +service: + auth: false + base-path: "" + endpoints: + stream: + method: POST + path: /stream + request: + name: StreamCompletionRequest + body: + properties: + query: string + response-stream: + type: StreamedCompletion + format: sse + terminator: "[[DONE]]" diff --git a/seed/pydantic-v2/server-sent-events/.mock/fern.config.json b/seed/pydantic-v2/server-sent-events/.mock/fern.config.json new file mode 100644 index 00000000000..4c8e54ac313 --- /dev/null +++ b/seed/pydantic-v2/server-sent-events/.mock/fern.config.json @@ -0,0 +1 @@ +{"organization": "fern-test", "version": "*"} \ No newline at end of file diff --git a/seed/pydantic-v2/server-sent-events/.mock/generators.yml b/seed/pydantic-v2/server-sent-events/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/pydantic-v2/server-sent-events/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/pydantic-v2/server-sent-events/resources/completions/types/streamed_completion.py b/seed/pydantic-v2/server-sent-events/resources/completions/types/streamed_completion.py new file mode 100644 index 00000000000..eab550662ab --- /dev/null +++ b/seed/pydantic-v2/server-sent-events/resources/completions/types/streamed_completion.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel +from typing import Optional +from dt import datetime +from core.datetime_utils import serialize_datetime + + +class StreamedCompletion(BaseModel): + delta: str + tokens: Optional[int] = None + + class Config: + frozen = True + smart_union = True + json_encoders = {datetime: serialize_datetime} diff --git a/seed/pydantic-v2/server-sent-events/snippet-templates.json b/seed/pydantic-v2/server-sent-events/snippet-templates.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/server-sent-events/snippet.json b/seed/pydantic-v2/server-sent-events/snippet.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/seed/pydantic-v2/simple-fhir/.mock/definition/__package__.yml b/seed/pydantic-v2/simple-fhir/.mock/definition/__package__.yml new file mode 100644 index 00000000000..0821c83ceac --- /dev/null +++ b/seed/pydantic-v2/simple-fhir/.mock/definition/__package__.yml @@ -0,0 +1,58 @@ +service: + auth: false + base-path: "" + endpoints: + getAccount: + method: GET + path: /account/{account_id} + path-parameters: + account_id: string + response: Account + +types: + Memo: + properties: + description: string + account: optional + + BaseResource: + properties: + id: string + related_resources: list + memo: Memo + + ResourceList: + discriminated: false + union: + - Account + - Patient + - Practitioner + - Script + + Account: + extends: BaseResource + properties: + resource_type: literal<"Account"> + name: string + patient: optional + practitioner: optional + + Patient: + extends: BaseResource + properties: + resource_type: literal<"Patient"> + name: string + scripts: list