diff --git a/generators/java-v2/ast/src/ast/ClassReference.ts b/generators/java-v2/ast/src/ast/ClassReference.ts index 12a2df621251..86cd61dba4c0 100644 --- a/generators/java-v2/ast/src/ast/ClassReference.ts +++ b/generators/java-v2/ast/src/ast/ClassReference.ts @@ -9,6 +9,13 @@ export declare namespace ClassReference { packageName: string; /* Force the class reference to be fully qualified */ fullyQualified?: boolean; + /** + * The chain of enclosing classes (outermost first) when this is a nested class, + * not including `name`. For example, the nested class `PostRootRequest.Bar` has + * `name: "Bar"` and `enclosingClasses: ["PostRootRequest"]`. Only the outermost + * enclosing class is imported; the reference is written using the dotted path. + */ + enclosingClasses?: string[]; } } @@ -16,20 +23,24 @@ export class ClassReference extends AstNode { public readonly name: string; public readonly packageName: string; public readonly fullyQualified: boolean; + public readonly enclosingClasses: string[]; - constructor({ name, packageName, fullyQualified }: ClassReference.Args) { + constructor({ name, packageName, fullyQualified, enclosingClasses }: ClassReference.Args) { super(); this.name = name; this.packageName = packageName; this.fullyQualified = fullyQualified ?? false; + this.enclosingClasses = enclosingClasses ?? []; } public write(writer: Writer): void { - writer.addImport(`${this.packageName}.${this.name}`); + const topLevelClassName = this.enclosingClasses[0] ?? this.name; + const qualifiedName = [...this.enclosingClasses, this.name].join("."); + writer.addImport(`${this.packageName}.${topLevelClassName}`); if (this.fullyQualified) { - writer.write(`${this.packageName}.${this.name}`); + writer.write(`${this.packageName}.${qualifiedName}`); return; } - writer.write(this.name); + writer.write(qualifiedName); } } diff --git a/generators/java-v2/ast/src/ast/TypeLiteral.ts b/generators/java-v2/ast/src/ast/TypeLiteral.ts index ba5c1c546c76..cd3ea83c4270 100644 --- a/generators/java-v2/ast/src/ast/TypeLiteral.ts +++ b/generators/java-v2/ast/src/ast/TypeLiteral.ts @@ -49,6 +49,13 @@ interface Builder { export interface BuilderParameter { name: string; value: TypeLiteral; + /** + * Whether this property is a required stage in the generated staged builder. When set, it takes + * precedence over inferring required-ness from the emitted value. This matters because a nullable + * property may be emitted as a raw (non-Optional) value yet still belong on the builder's final + * stage rather than the required staged chain. + */ + isRequired?: boolean; } interface Bytes { @@ -526,7 +533,7 @@ export class TypeLiteral extends AstNode { } public orderBuilderParameters(parameters: java.BuilderParameter[]): java.BuilderParameter[] { - const hasRequiredFields = parameters.some((p) => !p.value.isOptional() && !this.isCollection(p.value)); + const hasRequiredFields = parameters.some((p) => this.isRequiredBuilderParameter(p)); if (!hasRequiredFields) { return parameters.sort((a, b) => { @@ -545,8 +552,8 @@ export class TypeLiteral extends AstNode { } return parameters.sort((a, b) => { - const aIsNonRequired = this.isNonRequired(a.value); - const bIsNonRequired = this.isNonRequired(b.value); + const aIsNonRequired = !this.isRequiredBuilderParameter(a); + const bIsNonRequired = !this.isRequiredBuilderParameter(b); if (aIsNonRequired && !bIsNonRequired) { return 1; @@ -564,6 +571,13 @@ export class TypeLiteral extends AstNode { return internalType === "list" || internalType === "set" || internalType === "map"; } + private isRequiredBuilderParameter(parameter: java.BuilderParameter): boolean { + if (parameter.isRequired != null) { + return parameter.isRequired; + } + return !this.isNonRequired(parameter.value); + } + private isNonRequired(value: TypeLiteral): boolean { return value.isOptional() || this.isCollection(value); } diff --git a/generators/java-v2/ast/src/ast/__test__/ClassReference.test.ts b/generators/java-v2/ast/src/ast/__test__/ClassReference.test.ts new file mode 100644 index 000000000000..bcb51a451d46 --- /dev/null +++ b/generators/java-v2/ast/src/ast/__test__/ClassReference.test.ts @@ -0,0 +1,75 @@ +import { describe, expect, it } from "vitest"; +import { ClassReference } from "../ClassReference.js"; +import { Writer } from "../core/Writer.js"; + +function makeWriter(): Writer { + return new Writer({ packageName: "com.example", customConfig: {} as never }); +} + +describe("ClassReference", () => { + describe("without enclosingClasses", () => { + it("writes the simple class name and imports the full package path", () => { + const ref = new ClassReference({ name: "Foo", packageName: "com.example.types" }); + const writer = makeWriter(); + ref.write(writer); + expect(writer.toString()).toBe("Foo"); + expect([...writer.getImports()]).toContain("com.example.types.Foo"); + }); + + it("writes the fully qualified name when fullyQualified is true", () => { + const ref = new ClassReference({ name: "Foo", packageName: "com.example.types", fullyQualified: true }); + const writer = makeWriter(); + ref.write(writer); + expect(writer.toString()).toBe("com.example.types.Foo"); + }); + }); + + describe("with enclosingClasses (nested class)", () => { + it("writes Parent.Child and imports only the outermost class", () => { + const ref = new ClassReference({ + name: "Child", + packageName: "com.example.types", + enclosingClasses: ["Parent"] + }); + const writer = makeWriter(); + ref.write(writer); + // Written name uses dotted path + expect(writer.toString()).toBe("Parent.Child"); + // Import is for the top-level class only — NOT Parent.Child + expect([...writer.getImports()]).toContain("com.example.types.Parent"); + expect([...writer.getImports()]).not.toContain("com.example.types.Parent.Child"); + expect([...writer.getImports()]).not.toContain("com.example.types.Child"); + }); + + it("writes A.B.C and imports only the outermost class for deep nesting", () => { + const ref = new ClassReference({ + name: "C", + packageName: "com.example.types", + enclosingClasses: ["A", "B"] + }); + const writer = makeWriter(); + ref.write(writer); + expect(writer.toString()).toBe("A.B.C"); + expect([...writer.getImports()]).toContain("com.example.types.A"); + expect([...writer.getImports()]).not.toContain("com.example.types.A.B"); + expect([...writer.getImports()]).not.toContain("com.example.types.A.B.C"); + }); + + it("writes the fully qualified dotted path when fullyQualified is true", () => { + const ref = new ClassReference({ + name: "Bar", + packageName: "com.example.requests", + enclosingClasses: ["PostRootRequest"], + fullyQualified: true + }); + const writer = makeWriter(); + ref.write(writer); + expect(writer.toString()).toBe("com.example.requests.PostRootRequest.Bar"); + }); + + it("defaults enclosingClasses to empty array", () => { + const ref = new ClassReference({ name: "Solo", packageName: "com.example" }); + expect(ref.enclosingClasses).toEqual([]); + }); + }); +}); diff --git a/generators/java-v2/ast/src/custom-config/BaseJavaCustomConfigSchema.ts b/generators/java-v2/ast/src/custom-config/BaseJavaCustomConfigSchema.ts index 59b2049efc4f..951fcf448d53 100644 --- a/generators/java-v2/ast/src/custom-config/BaseJavaCustomConfigSchema.ts +++ b/generators/java-v2/ast/src/custom-config/BaseJavaCustomConfigSchema.ts @@ -26,6 +26,7 @@ export const BaseJavaCustomConfigSchema = z.object({ "use-default-request-parameter-values": z.boolean().optional(), "enable-wire-tests": z.boolean().default(false), "collapse-optional-nullable": z.boolean().optional(), + "use-nullable-annotation": z.boolean().optional(), "custom-readme-sections": z.array(CustomReadmeSectionSchema).optional(), "custom-pager-name": z.string().optional(), "offset-semantics": z.enum(["item-index", "page-index"]).optional(), diff --git a/generators/java-v2/dynamic-snippets/src/DynamicSnippetsGenerator.ts b/generators/java-v2/dynamic-snippets/src/DynamicSnippetsGenerator.ts index 5937ea97e6fe..4f43f3ad7133 100644 --- a/generators/java-v2/dynamic-snippets/src/DynamicSnippetsGenerator.ts +++ b/generators/java-v2/dynamic-snippets/src/DynamicSnippetsGenerator.ts @@ -15,13 +15,15 @@ export class DynamicSnippetsGenerator extends AbstractDynamicSnippetsGenerator< constructor({ ir, config, - options = {} + options = {}, + inlineTypeIds }: { ir: FernIr.dynamic.DynamicIntermediateRepresentation; config: FernGeneratorExec.GeneratorConfig; options?: Options; + inlineTypeIds?: Set; }) { - super(new DynamicSnippetsGeneratorContext({ ir, config, options })); + super(new DynamicSnippetsGeneratorContext({ ir, config, options, inlineTypeIds })); } public async generate( diff --git a/generators/java-v2/dynamic-snippets/src/EndpointSnippetGenerator.ts b/generators/java-v2/dynamic-snippets/src/EndpointSnippetGenerator.ts index d518f0903c2a..0e8c80d8f965 100644 --- a/generators/java-v2/dynamic-snippets/src/EndpointSnippetGenerator.ts +++ b/generators/java-v2/dynamic-snippets/src/EndpointSnippetGenerator.ts @@ -688,8 +688,18 @@ export class EndpointSnippetGenerator { if (isCollapsedOptionalNullable) { return this.context.getOptionalNullableOf(convertedValue); } else { + // The generated client method accepts the body as a single Optional + // argument and therefore requires an explicit Optional.of(...). When the + // body nests optional/nullable (e.g. optional>), converting + // body.value.value yields an Optional literal that renders without + // Optional.of(...), and wrapping it again is deduped away. Convert the + // fully unwrapped type so the explicit Optional.of(...) is preserved. return java.TypeLiteral.optional({ - value: convertedValue, + value: this.context.dynamicTypeLiteralMapper.convert({ + typeReference: stripOptionalAndNullable(body.value), + value, + as: "request" + }), useOf: true }); } @@ -855,22 +865,25 @@ export class EndpointSnippetGenerator { })); this.context.errors.unscope(); + const requestClassReference = java.classReference({ + name: this.context.getClassName(request.declaration.name), + packageName: this.context.getRequestsPackageName(request.declaration.fernFilepath) + }); + this.context.errors.scope(Scope.RequestBody); const requestBodyFields = request.body != null ? this.getInlinedRequestBodyBuilderParameters({ body: request.body, value: snippet.requestBody, - filePropertyInfo + filePropertyInfo, + enclosing: requestClassReference }) : []; this.context.errors.unscope(); return java.TypeLiteral.builder({ - classReference: java.classReference({ - name: this.context.getClassName(request.declaration.name), - packageName: this.context.getRequestsPackageName(request.declaration.fernFilepath) - }), + classReference: requestClassReference, parameters: [...pathParameterFields, ...headerFields, ...queryParameterFields, ...requestBodyFields] }); } @@ -933,15 +946,21 @@ export class EndpointSnippetGenerator { private getInlinedRequestBodyBuilderParameters({ body, value, - filePropertyInfo + filePropertyInfo, + enclosing }: { body: FernIr.dynamic.InlinedRequestBody; value: unknown; filePropertyInfo: FilePropertyInfo; + enclosing: java.ClassReference; }): java.BuilderParameter[] { switch (body.type) { case "properties": - return this.getInlinedRequestBodyPropertyBuilderParameters({ parameters: body.value, value }); + return this.getInlinedRequestBodyPropertyBuilderParameters({ + parameters: body.value, + value, + enclosing + }); case "referenced": return [this.getReferencedRequestBodyPropertyBuilderParameter({ body, value })]; case "fileUpload": @@ -1002,10 +1021,12 @@ export class EndpointSnippetGenerator { private getInlinedRequestBodyPropertyBuilderParameters({ parameters, - value + value, + enclosing }: { parameters: FernIr.dynamic.NamedParameter[]; value: unknown; + enclosing: java.ClassReference; }): java.BuilderParameter[] { const bodyProperties = this.context.associateByWireValue({ parameters, @@ -1015,12 +1036,23 @@ export class EndpointSnippetGenerator { (parameter) => !this.context.isDirectLiteral(parameter.typeReference) ); const sortedProperties = this.context.sortTypeInstancesByRequiredFirst(filteredProperties, parameters); + const reservedNames = new Set([...enclosing.enclosingClasses, enclosing.name]); + const siblingPropertyNames = new Set( + parameters.map((parameter) => this.context.getClassName(parameter.name.name)) + ); return sortedProperties.map((parameter) => ({ name: this.context.getMethodName(parameter.name.name), value: this.context.dynamicTypeLiteralMapper.convert({ typeReference: parameter.typeReference, value: parameter.value, - as: "request" + as: "request", + nestedClassReference: this.context.dynamicTypeLiteralMapper.resolveInlineNestedClassReference({ + enclosing, + baseName: this.context.getClassName(parameter.name.name), + typeReference: parameter.typeReference, + reservedNames, + siblingPropertyNames + }) }) })); } diff --git a/generators/java-v2/dynamic-snippets/src/__test__/DynamicSnippetsGenerator.test.ts b/generators/java-v2/dynamic-snippets/src/__test__/DynamicSnippetsGenerator.test.ts index e16118371caf..9df0b1db876b 100644 --- a/generators/java-v2/dynamic-snippets/src/__test__/DynamicSnippetsGenerator.test.ts +++ b/generators/java-v2/dynamic-snippets/src/__test__/DynamicSnippetsGenerator.test.ts @@ -83,3 +83,145 @@ describe("snippets (exported-client-class-name)", () => { expect(snippet).toContain("BaseAcme client = BaseAcme"); }); }); + +/** + * Inline type naming: when `enable-inline-types` is on and `inlineTypeIds` is supplied, the + * dynamic snippet generator must reference nested classes (e.g. `DiscriminatedUnion1.Type1`) + * rather than the flat top-level names the dynamic IR would otherwise produce + * (e.g. `DiscriminatedUnion1InlineType1`). + * + * The `inlineTypeIds` set normally comes from the full IR (computed in SdkGeneratorCli) and is + * threaded through the generator. In tests we supply it directly so we can exercise the naming + * logic without running the full Java v1 generator. + */ +describe("snippets (inline type naming)", () => { + // The type IDs that v1 emits as nested classes for the java-inline-types fixture when + // enable-inline-types is true. These match the dynamic IR type IDs (same namespace). + const inlineTypeIds = new Set([ + "type_:RequestTypeInlineType1", + "type_:RootType1", + "type_:RootType1FooMapValue", + "type_:RootType1FooListItem", + "type_:RootType1FooSetItem", + "type_:RootType1InlineType1", + "type_:RootType1InlineType1NestedInlineType1", + "type_:DiscriminatedUnion1InlineType1", + "type_:DiscriminatedUnion1InlineType1InlineType1", + "type_:DiscriminatedUnion1InlineType2", + "type_:UndiscriminatedUnion1InlineType1", + "type_:UndiscriminatedUnion1InlineType1InlineType1", + "type_:UndiscriminatedUnion1InlineType2", + "type_:InlineEnum1", + "type_:UndiscriminatedUnion1DiscriminatedUnion1InlineType1", + "type_:UndiscriminatedUnion1DiscriminatedUnion1InlineType1InlineType1", + "type_:UndiscriminatedUnion1DiscriminatedUnion1InlineType2", + "type_:UndiscriminatedUnion1InlineEnum1", + "type_:UndiscriminatedUnion1InlineListItem1", + "type_:UndiscriminatedUnion1InlineSetItem1", + "type_:UndiscriminatedUnion1InlineMapItem1", + "type_:MapResponseValue", + "type_:MapResponseValueNested", + "type_:AliasInlineValue" + ]); + + function buildInlineGenerator(): ReturnType { + return buildDynamicSnippetsGenerator({ + irFilepath: AbsoluteFilePath.of(join(DYNAMIC_IR_TEST_DEFINITIONS_DIRECTORY, "java-inline-types.json")), + config: buildGeneratorConfig({ + customConfig: { + "enable-inline-types": true, + "wrapped-aliases": true + } + }), + inlineTypeIds + }); + } + + test("discriminated union variant uses nested class name (DiscriminatedUnion1.Type1), not flat top-level name", async () => { + const generator = buildInlineGenerator(); + + const response = await generator.generate({ + endpoint: { method: "POST", path: "/root/discriminated-union" }, + baseURL: undefined, + environment: undefined, + auth: undefined, + pathParameters: undefined, + queryParameters: undefined, + headers: undefined, + requestBody: { + bar: { + type: "type1", + foo: "foo", + // DiscriminatedUnion1InlineType1InlineType1 has foo + ref (no bar) + bar: { foo: "foo", ref: { foo: "foo" } }, + ref: { foo: "foo" } + }, + foo: "foo" + } + }); + + expect(response.errors).toBeUndefined(); + const snippet = response.snippet ?? ""; + // v1 nests the variant type as DiscriminatedUnion1.Type1, not the flat DiscriminatedUnion1InlineType1 + expect(snippet).toContain("DiscriminatedUnion1.Type1"); + expect(snippet).not.toContain("DiscriminatedUnion1InlineType1"); + }); + + test("object inline property uses nested class name (PostRootRequest.Bar), not flat top-level name", async () => { + const generator = buildInlineGenerator(); + + const response = await generator.generate({ + endpoint: { method: "POST", path: "/root/root" }, + baseURL: undefined, + environment: undefined, + auth: undefined, + pathParameters: undefined, + queryParameters: undefined, + headers: undefined, + requestBody: { + bar: { foo: "foo" }, + foo: "foo" + } + }); + + expect(response.errors).toBeUndefined(); + const snippet = response.snippet ?? ""; + // The `bar` property of PostRootRequest is an inline type; v1 names it PostRootRequest.Bar + expect(snippet).toContain("PostRootRequest.Bar"); + expect(snippet).not.toContain("RequestTypeInlineType1"); + }); + + test("without inlineTypeIds flat names are used (regression guard)", async () => { + // When inlineTypeIds is not supplied (empty), the generator must fall back to the + // top-level dynamic-IR names so existing users without inline types are unaffected. + const generator = buildDynamicSnippetsGenerator({ + irFilepath: AbsoluteFilePath.of(join(DYNAMIC_IR_TEST_DEFINITIONS_DIRECTORY, "java-inline-types.json")), + config: buildGeneratorConfig({ + customConfig: { + "enable-inline-types": true, + "wrapped-aliases": true + } + }) + // No inlineTypeIds — should behave as before the fix + }); + + const response = await generator.generate({ + endpoint: { method: "POST", path: "/root/root" }, + baseURL: undefined, + environment: undefined, + auth: undefined, + pathParameters: undefined, + queryParameters: undefined, + headers: undefined, + requestBody: { + bar: { foo: "foo" }, + foo: "foo" + } + }); + + const snippet = response.snippet ?? ""; + // Without inlineTypeIds, the flat declaration name is used + expect(snippet).toContain("RequestTypeInlineType1"); + expect(snippet).not.toContain("PostRootRequest.Bar"); + }); +}); diff --git a/generators/java-v2/dynamic-snippets/src/__test__/utils/buildDynamicSnippetsGenerator.ts b/generators/java-v2/dynamic-snippets/src/__test__/utils/buildDynamicSnippetsGenerator.ts index 1a0d36ef97f8..0dc941a5b6ac 100644 --- a/generators/java-v2/dynamic-snippets/src/__test__/utils/buildDynamicSnippetsGenerator.ts +++ b/generators/java-v2/dynamic-snippets/src/__test__/utils/buildDynamicSnippetsGenerator.ts @@ -6,12 +6,14 @@ import { DynamicSnippetsGenerator } from "../../DynamicSnippetsGenerator.js"; export function buildDynamicSnippetsGenerator({ irFilepath, - config + config, + inlineTypeIds }: { irFilepath: AbsoluteFilePath; config: FernGeneratorExec.GeneratorConfig; + inlineTypeIds?: Set; }): DynamicSnippetsGenerator { const content = readFileSync(irFilepath, "utf-8"); const ir = JSON.parse(content); - return new DynamicSnippetsGenerator({ ir, config, options: { style: Style.Concise } }); + return new DynamicSnippetsGenerator({ ir, config, options: { style: Style.Concise }, inlineTypeIds }); } diff --git a/generators/java-v2/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts b/generators/java-v2/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts index d40dd89bbb6a..25ce2d149b9b 100644 --- a/generators/java-v2/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts +++ b/generators/java-v2/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts @@ -37,17 +37,26 @@ export class DynamicSnippetsGeneratorContext extends AbstractDynamicSnippetsGene public dynamicTypeMapper: DynamicTypeMapper; public dynamicTypeLiteralMapper: DynamicTypeLiteralMapper; public filePropertyMapper: FilePropertyMapper; + /** + * The set of type IDs that the v1 generator emits as nested (inline) classes rather than + * top-level types. The dynamic IR does not carry the `inline` flag, so the v2 SDK generator + * computes this from the full IR and threads it through. Used to mirror v1's nested-class + * naming when referencing inline types in snippets. + */ + public inlineTypeIds: Set; constructor({ ir, config, options, - sharedCustomConfig + sharedCustomConfig, + inlineTypeIds }: { ir: FernIr.dynamic.DynamicIntermediateRepresentation; config: FernGeneratorExec.GeneratorConfig; options?: Options; sharedCustomConfig?: BaseJavaCustomConfigSchema; + inlineTypeIds?: Set; }) { super({ ir, config, options }); this.ir = ir; @@ -55,6 +64,7 @@ export class DynamicSnippetsGeneratorContext extends AbstractDynamicSnippetsGene this.dynamicTypeMapper = new DynamicTypeMapper({ context: this }); this.dynamicTypeLiteralMapper = new DynamicTypeLiteralMapper({ context: this }); this.filePropertyMapper = new FilePropertyMapper({ context: this }); + this.inlineTypeIds = inlineTypeIds ?? new Set(); } public clone(): DynamicSnippetsGeneratorContext { @@ -62,10 +72,41 @@ export class DynamicSnippetsGeneratorContext extends AbstractDynamicSnippetsGene ir: this.ir, config: this.config, options: this.options, - sharedCustomConfig: this.customConfig + sharedCustomConfig: this.customConfig, + inlineTypeIds: this.inlineTypeIds + }); + } + + public isInlineType(typeId: string): boolean { + return this.inlineTypeIds.has(typeId); + } + + /** + * Builds a reference to a class nested within `enclosing`. The resulting reference imports the + * outermost enclosing class and is written using the dotted path (e.g. `PostRootRequest.Bar`). + */ + public getNestedInlineClassReference({ + enclosing, + name + }: { + enclosing: java.ClassReference; + name: string; + }): java.ClassReference { + return java.classReference({ + name, + packageName: enclosing.packageName, + enclosingClasses: [...enclosing.enclosingClasses, enclosing.name] }); } + public wrappedAliases(): boolean { + return this.customConfig?.["wrapped-aliases"] ?? false; + } + + public enableInlineTypes(): boolean { + return this.customConfig?.["enable-inline-types"] ?? false; + } + public getClassName(name: FernIr.Name): string { return this.getName(name.pascalCase.safeName); } @@ -426,6 +467,14 @@ export class DynamicSnippetsGeneratorContext extends AbstractDynamicSnippetsGene return this.customConfig?.["inline-file-properties"] ?? false; } + public usesNullableAnnotation(): boolean { + return this.customConfig?.["use-nullable-annotation"] === true; + } + + public usesOptionalNullable(): boolean { + return this.customConfig?.["collapse-optional-nullable"] === true; + } + private getPackageNameSegments(fernFilepath: FernIr.dynamic.FernFilepath): string[] { return fernFilepath.packagePath.map((segment: FernIr.dynamic.Name) => this.getPackageNameSegment(segment)); } diff --git a/generators/java-v2/dynamic-snippets/src/context/DynamicTypeLiteralMapper.ts b/generators/java-v2/dynamic-snippets/src/context/DynamicTypeLiteralMapper.ts index 076e87490586..b9cad1217dd0 100644 --- a/generators/java-v2/dynamic-snippets/src/context/DynamicTypeLiteralMapper.ts +++ b/generators/java-v2/dynamic-snippets/src/context/DynamicTypeLiteralMapper.ts @@ -14,6 +14,11 @@ export declare namespace DynamicTypeLiteralMapper { // Set to true when we've detected a nested optional+nullable type that should // collapse into OptionalNullable (only relevant when collapse-optional-nullable is enabled). isCollapsedOptionalNullable?: boolean; + // When the value resolves to an inline named type that v1 emits as a nested class, this is + // the class reference to use instead of the top-level declaration name (e.g. the nested + // `PostRootRequest.Bar` rather than the standalone `RequestTypeInlineType1`). Propagated + // through container wrappers (optional/nullable/list/set/map value) to the inner named type. + nestedClassReference?: java.ClassReference; } // Identifies what the type is being converted as, which sometimes influences how @@ -29,7 +34,11 @@ export class DynamicTypeLiteralMapper { } private usesOptionalNullable(): boolean { - return this.context.customConfig?.["collapse-optional-nullable"] === true; + return this.context.usesOptionalNullable(); + } + + private usesNullableAnnotation(): boolean { + return this.context.usesNullableAnnotation(); } private wrapInOptionalIfNotNop( @@ -46,6 +55,33 @@ export class DynamicTypeLiteralMapper { return java.TypeLiteral.optional({ value, useOf }); } + // Wraps an already-converted inner value for an `optional`/`nullable` wrapper type, honoring + // the `use-nullable-annotation` (raw, no wrapper) and `collapse-optional-nullable` + // (OptionalNullable) configs. `propagatedCollapse` is set when an outer optional+nullable + // collapsed into this node. + private wrapNullableOrOptionalValue({ + value, + wrapperType, + useOf, + propagatedCollapse + }: { + value: java.TypeLiteral; + wrapperType: "optional" | "nullable"; + useOf: boolean; + propagatedCollapse: boolean; + }): java.TypeLiteral { + if (java.TypeLiteral.isNop(value)) { + return value; + } + if (wrapperType === "nullable" && this.usesNullableAnnotation()) { + return value; + } + if (propagatedCollapse || (this.usesOptionalNullable() && wrapperType === "nullable")) { + return this.context.getOptionalNullableOf(value); + } + return java.TypeLiteral.optional({ value, useOf }); + } + public convert(args: DynamicTypeLiteralMapper.Args): java.TypeLiteral { // eslint-disable-next-line eqeqeq if (args.value === null) { @@ -63,11 +99,21 @@ export class DynamicTypeLiteralMapper { } switch (args.typeReference.type) { case "list": - return this.convertList({ list: args.typeReference.value, value: args.value, as: args.as }); + return this.convertList({ + list: args.typeReference.value, + value: args.value, + as: args.as, + nestedClassReference: args.nestedClassReference + }); case "literal": return this.convertLiteral({ literal: args.typeReference.value, value: args.value }); case "map": - return this.convertMap({ map: args.typeReference, value: args.value, as: args.as }); + return this.convertMap({ + map: args.typeReference, + value: args.value, + as: args.as, + nestedClassReference: args.nestedClassReference + }); case "named": { const named = this.context.resolveNamedType({ typeId: args.typeReference.value }); if (named == null) { @@ -77,28 +123,35 @@ export class DynamicTypeLiteralMapper { named, value: args.value, as: args.as, - inUndiscriminatedUnion: args.inUndiscriminatedUnion + inUndiscriminatedUnion: args.inUndiscriminatedUnion, + nestedClassReference: args.nestedClassReference }); } case "nullable": case "optional": { + const wrapperType = args.typeReference.type; + const inner = args.typeReference.value; if ( args.value === undefined || (typeof args.value === "object" && args.value !== null && Object.keys(args.value).length === 0 && - args.typeReference.value.type === "named") + inner.type === "named") ) { - // Use OptionalNullable.absent() only when the type is truly a collapsed - // optional+nullable (either detected here or propagated from outer recursion). - const isCollapsed = - args.isCollapsedOptionalNullable || - (this.usesOptionalNullable() && - (args.typeReference.value.type === "optional" || - args.typeReference.value.type === "nullable")); - if (isCollapsed) { - return this.context.getOptionalNullableAbsent(); - } else { + // In use-nullable-annotation mode a nullable is rendered as its raw type, so there + // is no Optional/OptionalNullable wrapper to emit an "absent" sentinel for; fall + // through and build the value directly below. + if (!(wrapperType === "nullable" && this.usesNullableAnnotation())) { + // Use OptionalNullable.absent() when the type collapses to OptionalNullable + // (a standalone nullable, a nested optional+nullable, or propagated from outer + // recursion in collapse-optional-nullable mode). + const isCollapsed = + args.isCollapsedOptionalNullable || + (this.usesOptionalNullable() && + (wrapperType === "nullable" || inner.type === "optional" || inner.type === "nullable")); + if (isCollapsed) { + return this.context.getOptionalNullableAbsent(); + } return java.TypeLiteral.reference( java.invokeMethod({ on: java.classReference({ @@ -112,31 +165,39 @@ export class DynamicTypeLiteralMapper { } } - if (args.typeReference.value.type === "list") { - const listLiteral = this.convertList({ list: args.typeReference.value.value, value: args.value }); - return this.wrapInOptionalIfNotNop(listLiteral, true, args.isCollapsedOptionalNullable === true); - } - // When using OptionalNullable mode and we have nested optional/nullable, // skip wrapping since they collapse into a single OptionalNullable - if ( - this.usesOptionalNullable() && - (args.typeReference.value.type === "optional" || args.typeReference.value.type === "nullable") - ) { + if (this.usesOptionalNullable() && (inner.type === "optional" || inner.type === "nullable")) { return this.convert({ - typeReference: args.typeReference.value, + typeReference: inner, value: args.value, as: args.as, inUndiscriminatedUnion: args.inUndiscriminatedUnion, - isCollapsedOptionalNullable: true + isCollapsedOptionalNullable: true, + nestedClassReference: args.nestedClassReference + }); + } + + if (inner.type === "list") { + const listLiteral = this.convertList({ + list: inner.value, + value: args.value, + nestedClassReference: args.nestedClassReference + }); + return this.wrapNullableOrOptionalValue({ + value: listLiteral, + wrapperType, + useOf: true, + propagatedCollapse: args.isCollapsedOptionalNullable === true }); } const convertedValue = this.convert({ - typeReference: args.typeReference.value, + typeReference: inner, value: args.value, as: args.as, - inUndiscriminatedUnion: args.inUndiscriminatedUnion + inUndiscriminatedUnion: args.inUndiscriminatedUnion, + nestedClassReference: args.nestedClassReference }); // TODO(amckinney): The Java generator produces Map> whenever the value is an optional. // @@ -144,12 +205,22 @@ export class DynamicTypeLiteralMapper { // flag. // When in an undiscriminated union, we always use Optional.of() for optional types const useOf = args.as === "mapValue" || args.inUndiscriminatedUnion === true; - return this.wrapInOptionalIfNotNop(convertedValue, useOf, args.isCollapsedOptionalNullable === true); + return this.wrapNullableOrOptionalValue({ + value: convertedValue, + wrapperType, + useOf, + propagatedCollapse: args.isCollapsedOptionalNullable === true + }); } case "primitive": return this.convertPrimitive({ primitive: args.typeReference.value, value: args.value, as: args.as }); case "set": - return this.convertSet({ set: args.typeReference.value, value: args.value, as: args.as }); + return this.convertSet({ + set: args.typeReference.value, + value: args.value, + as: args.as, + nestedClassReference: args.nestedClassReference + }); case "unknown": return this.convertUnknown({ value: args.value }); default: @@ -160,11 +231,13 @@ export class DynamicTypeLiteralMapper { private convertList({ list, value, - as + as, + nestedClassReference }: { list: FernIr.dynamic.TypeReference; value: unknown; as?: DynamicTypeLiteralMapper.ConvertedAs; + nestedClassReference?: java.ClassReference; }): java.TypeLiteral { if (!Array.isArray(value)) { this.context.errors.add({ @@ -181,11 +254,21 @@ export class DynamicTypeLiteralMapper { values: value.map((v, index) => { this.context.errors.scope({ index }); try { - if (isItemOptional) { - const itemValue = this.convert({ typeReference: list.value, value: v, as }); - return this.wrapInOptionalIfNotNop(itemValue, true); + if (isItemOptional && (list.type === "optional" || list.type === "nullable")) { + const itemValue = this.convert({ + typeReference: list.value, + value: v, + as, + nestedClassReference + }); + return this.wrapNullableOrOptionalValue({ + value: itemValue, + wrapperType: list.type, + useOf: true, + propagatedCollapse: false + }); } - return this.convert({ typeReference: list, value: v, as }); + return this.convert({ typeReference: list, value: v, as, nestedClassReference }); } finally { this.context.errors.unscope(); } @@ -224,11 +307,13 @@ export class DynamicTypeLiteralMapper { private convertSet({ set, value, - as + as, + nestedClassReference }: { set: FernIr.dynamic.TypeReference; value: unknown; as?: DynamicTypeLiteralMapper.ConvertedAs; + nestedClassReference?: java.ClassReference; }): java.TypeLiteral { if (!Array.isArray(value)) { this.context.errors.add({ @@ -242,7 +327,7 @@ export class DynamicTypeLiteralMapper { values: value.map((v, index) => { this.context.errors.scope({ index }); try { - return this.convert({ typeReference: set, value: v, as }); + return this.convert({ typeReference: set, value: v, as, nestedClassReference }); } finally { this.context.errors.unscope(); } @@ -253,11 +338,13 @@ export class DynamicTypeLiteralMapper { private convertMap({ map, value, - as + as, + nestedClassReference }: { map: FernIr.dynamic.MapType; value: unknown; as?: DynamicTypeLiteralMapper.ConvertedAs; + nestedClassReference?: java.ClassReference; }): java.TypeLiteral { if (typeof value !== "object" || value == null) { this.context.errors.add({ @@ -277,7 +364,8 @@ export class DynamicTypeLiteralMapper { value: this.convert({ typeReference: map.value, value, - as: "mapValue" + as: "mapValue", + nestedClassReference }) }; } finally { @@ -291,12 +379,14 @@ export class DynamicTypeLiteralMapper { named, value, as, - inUndiscriminatedUnion + inUndiscriminatedUnion, + nestedClassReference }: { named: FernIr.dynamic.NamedType; value: unknown; as?: DynamicTypeLiteralMapper.ConvertedAs; inUndiscriminatedUnion?: boolean; + nestedClassReference?: java.ClassReference; }): java.TypeLiteral { switch (named.type) { case "alias": @@ -309,29 +399,43 @@ export class DynamicTypeLiteralMapper { }); return java.TypeLiteral.reference( java.invokeMethod({ - on: this.context.getJavaClassReferenceFromDeclaration({ - declaration: named.declaration - }), + on: + nestedClassReference ?? + this.context.getJavaClassReferenceFromDeclaration({ + declaration: named.declaration + }), method: "of", arguments_: [convertedValue] }) ); } - return this.convert({ typeReference: named.typeReference, value, as, inUndiscriminatedUnion }); + return this.convert({ + typeReference: named.typeReference, + value, + as, + inUndiscriminatedUnion, + nestedClassReference + }); case "discriminatedUnion": return this.convertDiscriminatedUnion({ discriminatedUnion: named, value, - as + as, + nestedClassReference }); case "enum": - return this.convertEnum({ enum_: named, value }); + return this.convertEnum({ enum_: named, value, nestedClassReference }); case "object": - return this.convertObject({ object_: named, value, as, inUndiscriminatedUnion }); + return this.convertObject({ object_: named, value, as, inUndiscriminatedUnion, nestedClassReference }); case "undiscriminatedUnion": // Don't pass inUndiscriminatedUnion here - we're AT the undiscriminated union level, // not within it. The flag should only apply to the variants within the union. - return this.convertUndiscriminatedUnion({ undiscriminatedUnion: named, value, as }); + return this.convertUndiscriminatedUnion({ + undiscriminatedUnion: named, + value, + as, + nestedClassReference + }); default: assertNever(named); } @@ -340,15 +444,19 @@ export class DynamicTypeLiteralMapper { private convertDiscriminatedUnion({ discriminatedUnion, value, - as + as, + nestedClassReference }: { discriminatedUnion: FernIr.dynamic.DiscriminatedUnionType; value: unknown; as?: DynamicTypeLiteralMapper.ConvertedAs; + nestedClassReference?: java.ClassReference; }): java.TypeLiteral { - const classReference = this.context.getJavaClassReferenceFromDeclaration({ - declaration: discriminatedUnion.declaration - }); + const classReference = + nestedClassReference ?? + this.context.getJavaClassReferenceFromDeclaration({ + declaration: discriminatedUnion.declaration + }); const discriminatedUnionTypeInstance = this.context.resolveDiscriminatedUnionTypeInstance({ discriminatedUnion, value @@ -357,6 +465,15 @@ export class DynamicTypeLiteralMapper { return java.TypeLiteral.nop(); } const unionVariant = discriminatedUnionTypeInstance.singleDiscriminatedUnionType; + // v1 emits a variant's inline type as a class nested within the union, named after the + // variant's discriminant value (see UnionGenerator). Mirror that here so snippet literals + // reference the real nested class rather than the standalone top-level name. + const reservedNames = new Set([...classReference.enclosingClasses, classReference.name]); + const siblingDiscriminantNames = new Set( + Object.values(discriminatedUnion.types).map((variant) => + this.context.getClassName(variant.discriminantValue.name) + ) + ); switch (unionVariant.type) { case "samePropertiesAsObject": { const named = this.context.resolveNamedType({ @@ -365,11 +482,25 @@ export class DynamicTypeLiteralMapper { if (named == null) { return java.TypeLiteral.nop(); } + const variantNestedClassReference = this.resolveInlineNestedClassReference({ + enclosing: classReference, + baseName: this.context.getClassName(unionVariant.discriminantValue.name), + typeReference: { type: "named", value: unionVariant.typeId }, + reservedNames, + siblingPropertyNames: siblingDiscriminantNames + }); return java.TypeLiteral.reference( java.invokeMethod({ on: classReference, method: this.context.getPropertyName(unionVariant.discriminantValue.name), - arguments_: [this.convertNamed({ named, value: discriminatedUnionTypeInstance.value, as })] + arguments_: [ + this.convertNamed({ + named, + value: discriminatedUnionTypeInstance.value, + as, + nestedClassReference: variantNestedClassReference + }) + ] }) ); } @@ -382,6 +513,13 @@ export class DynamicTypeLiteralMapper { this.context.errors.scope(unionVariant.discriminantValue.wireValue); // For primitive union variants, the property key is always "value" const propertyKey = "value"; + const variantNestedClassReference = this.resolveInlineNestedClassReference({ + enclosing: classReference, + baseName: this.context.getClassName(unionVariant.discriminantValue.name), + typeReference: unionVariant.typeReference, + reservedNames, + siblingPropertyNames: siblingDiscriminantNames + }); return java.TypeLiteral.reference( java.invokeMethod({ on: classReference, @@ -390,7 +528,8 @@ export class DynamicTypeLiteralMapper { this.convert({ typeReference: unionVariant.typeReference, value: record[propertyKey], - as + as, + nestedClassReference: variantNestedClassReference }) ] }) @@ -416,13 +555,20 @@ export class DynamicTypeLiteralMapper { object_, value, as, - inUndiscriminatedUnion + inUndiscriminatedUnion, + nestedClassReference }: { object_: FernIr.dynamic.ObjectType; value: unknown; as?: DynamicTypeLiteralMapper.ConvertedAs; inUndiscriminatedUnion?: boolean; + nestedClassReference?: java.ClassReference; }): java.TypeLiteral { + const classReference = + nestedClassReference ?? + this.context.getJavaClassReferenceFromDeclaration({ + declaration: object_.declaration + }); const valueRecord = this.context.getRecord(value) ?? {}; const properties = this.context.associateByWireValue({ parameters: object_.properties, @@ -451,8 +597,11 @@ export class DynamicTypeLiteralMapper { } } } - // Re-sort all properties (including newly added defaults) to match schema declaration order. - // Java staged builders require method calls in the exact order defined by the schema. + // Re-sort all properties (including newly added defaults) into schema declaration order. + // Defaults for missing required properties are appended above, so without this a defaulted + // required property would render after user-provided ones. orderBuilderParameters later + // partitions required-before-optional with a stable sort, preserving this schema order + // within each group as required by Java staged builders. const paramOrderMap = new Map(); const declaredWireValues = new Set(); object_.properties.forEach((param, index) => { @@ -466,6 +615,10 @@ export class DynamicTypeLiteralMapper { as === "request" ? properties.filter((property) => !this.context.isDirectLiteral(property.typeReference)) : properties; + const reservedNames = new Set([...classReference.enclosingClasses, classReference.name]); + const siblingPropertyNames = new Set( + object_.properties.map((property) => this.context.getClassName(property.name.name)) + ); const builderParameters: java.BuilderParameter[] = []; for (const property of filteredProperties) { this.context.errors.scope(property.name.wireValue); @@ -474,7 +627,14 @@ export class DynamicTypeLiteralMapper { typeReference: property.typeReference, value: property.value, as, - inUndiscriminatedUnion + inUndiscriminatedUnion, + nestedClassReference: this.resolveInlineNestedClassReference({ + enclosing: classReference, + baseName: this.context.getClassName(property.name.name), + typeReference: property.typeReference, + reservedNames, + siblingPropertyNames + }) }); // If a required property converts to nop (e.g., invalid enum value for the wrong // union variant), throw to reject this variant during undiscriminated union matching. @@ -487,7 +647,8 @@ export class DynamicTypeLiteralMapper { } builderParameters.push({ name: this.context.getMethodName(property.name.name), - value: convertedValue + value: convertedValue, + isRequired: this.isStagedBuilderProperty(property.typeReference) }); } finally { this.context.errors.unscope(); @@ -501,19 +662,206 @@ export class DynamicTypeLiteralMapper { if (rawValue != null) { builderParameters.push({ name: "additionalProperty", - value: java.TypeLiteral.raw(`"${this.escapeJavaString(key)}", ${rawValue}`) + value: java.TypeLiteral.raw(`"${this.escapeJavaString(key)}", ${rawValue}`), + isRequired: false }); } } } return java.TypeLiteral.builder({ - classReference: this.context.getJavaClassReferenceFromDeclaration({ - declaration: object_.declaration - }), + classReference, parameters: builderParameters }); } + /** + * Mirrors the v1 generator's inline-type naming (see ObjectGenerator / InlineTypeIdResolver): + * when a property's type resolves to an inline named type, v1 emits it as a class nested within + * the enclosing object. This walks the property's type reference (descending through container + * wrappers, applying the same name suffixes as v1) and, if it terminates in an inline named type, + * returns the nested class reference to use. Returns undefined for non-inline types, which fall + * back to the standalone top-level class name. + */ + public resolveInlineNestedClassReference({ + enclosing, + baseName, + typeReference, + reservedNames, + siblingPropertyNames + }: { + enclosing: java.ClassReference; + baseName: string; + typeReference: FernIr.dynamic.TypeReference; + reservedNames: Set; + siblingPropertyNames: Set; + }): java.ClassReference | undefined { + if (!this.context.enableInlineTypes()) { + return undefined; + } + switch (typeReference.type) { + case "optional": + case "nullable": + return this.resolveInlineNestedClassReference({ + enclosing, + baseName, + typeReference: typeReference.value, + reservedNames, + siblingPropertyNames + }); + case "list": + case "set": + return this.resolveInlineNestedClassReference({ + enclosing, + baseName: `${baseName}Item`, + typeReference: typeReference.value, + reservedNames, + siblingPropertyNames + }); + case "map": + return this.resolveInlineNestedClassReference({ + enclosing, + baseName: `${baseName}Value`, + typeReference: typeReference.value, + reservedNames, + siblingPropertyNames + }); + case "named": { + const typeId = typeReference.value; + const named = this.context.resolveNamedType({ typeId }); + if (named == null) { + return undefined; + } + // When aliases are not wrapped, v1 resolves through the alias to the underlying + // type, so descend to find the terminal (potentially inline) type. + if (named.type === "alias" && !this.context.wrappedAliases()) { + return this.resolveInlineNestedClassReference({ + enclosing, + baseName, + typeReference: named.typeReference, + reservedNames, + siblingPropertyNames + }); + } + if (!this.context.isInlineType(typeId)) { + return undefined; + } + let name = baseName; + while (reservedNames.has(name) || (siblingPropertyNames.has(name) && name !== baseName)) { + name = `${name}_`; + } + reservedNames.add(name); + return this.context.getNestedInlineClassReference({ enclosing, name }); + } + case "primitive": + case "literal": + case "unknown": + return undefined; + default: + assertNever(typeReference); + } + } + + /** + * Resolves the nested class reference for an inline member of an undiscriminated union. + * Unlike object properties and discriminated-union variants (whose nested name is derived + * from the property/discriminant name), v1 names an undiscriminated union's inline members + * after the member type's own name, with the union's name stripped as a prefix (see + * UndiscriminatedUnionGenerator). Descends through container wrappers to the terminal named + * type. + */ + private resolveUndiscriminatedInlineNestedClassReference({ + enclosing, + typeReference, + reservedNames, + unionPrefix + }: { + enclosing: java.ClassReference; + typeReference: FernIr.dynamic.TypeReference; + reservedNames: Set; + unionPrefix: string; + }): java.ClassReference | undefined { + if (!this.context.enableInlineTypes()) { + return undefined; + } + switch (typeReference.type) { + case "optional": + case "nullable": + case "list": + case "set": + return this.resolveUndiscriminatedInlineNestedClassReference({ + enclosing, + typeReference: typeReference.value, + reservedNames, + unionPrefix + }); + case "map": + return this.resolveUndiscriminatedInlineNestedClassReference({ + enclosing, + typeReference: typeReference.value, + reservedNames, + unionPrefix + }); + case "named": { + const typeId = typeReference.value; + const named = this.context.resolveNamedType({ typeId }); + if (named == null) { + return undefined; + } + if (named.type === "alias" && !this.context.wrappedAliases()) { + return this.resolveUndiscriminatedInlineNestedClassReference({ + enclosing, + typeReference: named.typeReference, + reservedNames, + unionPrefix + }); + } + if (!this.context.isInlineType(typeId)) { + return undefined; + } + let name = this.context.getClassName(named.declaration.name); + if (name.startsWith(unionPrefix) && name !== unionPrefix) { + name = name.substring(unionPrefix.length); + } + while (reservedNames.has(name)) { + name = `${name}_`; + } + return this.context.getNestedInlineClassReference({ enclosing, name }); + } + case "primitive": + case "literal": + case "unknown": + return undefined; + default: + assertNever(typeReference); + } + } + + /** + * Returns true when a property becomes a required stage in v1's staged builder. v1 stages + * fields that are neither optional, nullable, nor collections (list/set/map); those are all + * exposed on the final stage instead. This intentionally resolves aliases itself because the + * shared `isOptional` helper does not treat an alias to an optional type as optional. + */ + private isStagedBuilderProperty(typeReference: FernIr.dynamic.TypeReference): boolean { + switch (typeReference.type) { + case "optional": + case "nullable": + case "list": + case "set": + case "map": + return false; + case "named": { + const resolvedType = this.context.resolveNamedType({ typeId: typeReference.value }); + if (resolvedType != null && resolvedType.type === "alias") { + return this.isStagedBuilderProperty(resolvedType.typeReference); + } + return true; + } + default: + return true; + } + } + private convertToRawJavaLiteral(value: unknown): string | null { if (typeof value === "string") { return `"${this.escapeJavaString(value)}"`; @@ -616,15 +964,25 @@ export class DynamicTypeLiteralMapper { } } - private convertEnum({ enum_, value }: { enum_: FernIr.dynamic.EnumType; value: unknown }): java.TypeLiteral { + private convertEnum({ + enum_, + value, + nestedClassReference + }: { + enum_: FernIr.dynamic.EnumType; + value: unknown; + nestedClassReference?: java.ClassReference; + }): java.TypeLiteral { const name = this.getEnumValueName({ enum_, value }); if (name == null) { return java.TypeLiteral.nop(); } return java.TypeLiteral.enum_({ - classReference: this.context.getJavaClassReferenceFromDeclaration({ - declaration: enum_.declaration - }), + classReference: + nestedClassReference ?? + this.context.getJavaClassReferenceFromDeclaration({ + declaration: enum_.declaration + }), value: name }); } @@ -651,40 +1009,34 @@ export class DynamicTypeLiteralMapper { private convertUndiscriminatedUnion({ undiscriminatedUnion, value, - as + as, + nestedClassReference }: { undiscriminatedUnion: FernIr.dynamic.UndiscriminatedUnionType; value: unknown; as?: DynamicTypeLiteralMapper.ConvertedAs; + nestedClassReference?: java.ClassReference; }): java.TypeLiteral { + const classReference = + nestedClassReference ?? + this.context.getJavaClassReferenceFromDeclaration({ + declaration: undiscriminatedUnion.declaration + }); const result = this.findMatchingUndiscriminatedUnionType({ undiscriminatedUnion, value, - as + as, + enclosing: classReference }); if (result == null) { return java.TypeLiteral.nop(); } - if (this.context.isPrimitive(result.valueTypeReference)) { - // Primitive types overload the 'of' method rather than - // defining a separate method from the type. - return java.TypeLiteral.reference( - java.invokeMethod({ - on: this.context.getJavaClassReferenceFromDeclaration({ - declaration: undiscriminatedUnion.declaration - }), - method: "of", - arguments_: [result.typeInstantiation] - }) - ); - } - // Use simple 'of' method name for consistency across all union factory methods - // This matches the Java SDK's generated code pattern + // Use simple 'of' method name for consistency across all union factory methods. + // Primitive types overload 'of' rather than defining a separate method, but the + // generated call is identical, so this matches the Java SDK's generated code pattern. return java.TypeLiteral.reference( java.invokeMethod({ - on: this.context.getJavaClassReferenceFromDeclaration({ - declaration: undiscriminatedUnion.declaration - }), + on: classReference, method: "of", arguments_: [result.typeInstantiation] }) @@ -694,12 +1046,19 @@ export class DynamicTypeLiteralMapper { private findMatchingUndiscriminatedUnionType({ undiscriminatedUnion, value, - as + as, + enclosing }: { undiscriminatedUnion: FernIr.dynamic.UndiscriminatedUnionType; value: unknown; as?: DynamicTypeLiteralMapper.ConvertedAs; + enclosing: java.ClassReference; }): { valueTypeReference: FernIr.dynamic.TypeReference; typeInstantiation: java.TypeLiteral } | undefined { + // v1 emits an undiscriminated union's inline members as classes nested within the union, + // named after the member type (with the union's name stripped as a prefix). Mirror that so + // snippet literals reference the real nested class rather than the standalone top-level name. + const reservedNames = new Set([...enclosing.enclosingClasses, enclosing.name]); + const unionPrefix = this.context.getClassName(undiscriminatedUnion.declaration.name); for (const typeReference of undiscriminatedUnion.types) { const errorsBefore = this.context.errors.size(); try { @@ -707,7 +1066,13 @@ export class DynamicTypeLiteralMapper { typeReference, value, as, - inUndiscriminatedUnion: true + inUndiscriminatedUnion: true, + nestedClassReference: this.resolveUndiscriminatedInlineNestedClassReference({ + enclosing, + typeReference, + reservedNames: new Set(reservedNames), + unionPrefix + }) }); if (java.TypeLiteral.isNop(typeInstantiation) || this.context.errors.size() > errorsBefore) { diff --git a/generators/java-v2/dynamic-snippets/src/context/DynamicTypeMapper.ts b/generators/java-v2/dynamic-snippets/src/context/DynamicTypeMapper.ts index 31adac47a8b9..f196c7fbcea8 100644 --- a/generators/java-v2/dynamic-snippets/src/context/DynamicTypeMapper.ts +++ b/generators/java-v2/dynamic-snippets/src/context/DynamicTypeMapper.ts @@ -36,9 +36,31 @@ export class DynamicTypeMapper { } return this.convertNamed({ named }); } - case "optional": + case "optional": { + const inner = args.typeReference.value; + // collapse-optional-nullable: optional> / optional> collapse to OptionalNullable. + if (this.context.usesOptionalNullable() && (inner.type === "nullable" || inner.type === "optional")) { + return java.Type.generic(this.context.getOptionalNullableClassReference(), [ + this.convert({ typeReference: inner.value }) + ]); + } + return java.Type.optional(this.convert({ typeReference: inner })); + } case "nullable": { - return java.Type.optional(this.convert({ typeReference: args.typeReference.value })); + const inner = args.typeReference.value; + // use-nullable-annotation: nullable is rendered as the raw type X (annotated `@Nullable`). + if (this.context.usesNullableAnnotation()) { + return this.convert({ typeReference: inner }); + } + // collapse-optional-nullable: nullable is rendered as OptionalNullable; + // nullable> / nullable> collapse into a single OptionalNullable. + if (this.context.usesOptionalNullable()) { + const collapsed = inner.type === "optional" || inner.type === "nullable" ? inner.value : inner; + return java.Type.generic(this.context.getOptionalNullableClassReference(), [ + this.convert({ typeReference: collapsed }) + ]); + } + return java.Type.optional(this.convert({ typeReference: inner })); } case "primitive": return this.convertPrimitive({ primitive: args.typeReference.value }); diff --git a/generators/java-v2/sdk/src/SdkGeneratorCli.ts b/generators/java-v2/sdk/src/SdkGeneratorCli.ts index 28692f459d3c..c21e1cb6d75f 100644 --- a/generators/java-v2/sdk/src/SdkGeneratorCli.ts +++ b/generators/java-v2/sdk/src/SdkGeneratorCli.ts @@ -62,9 +62,18 @@ export class SdkGeneratorCLI extends AbstractJavaGeneratorCli( + Object.values(context.ir.types) + .filter((typeDeclaration) => typeDeclaration.inline === true) + .map((typeDeclaration) => typeDeclaration.name.typeId) + ); const sharedSnippetsGenerator = new DynamicSnippetsGenerator({ ir: convertedIr, - config: context.config + config: context.config, + inlineTypeIds }); // Pre-populate snippets cache with the shared generator (used by reference.md) diff --git a/generators/java-v2/sdk/src/SdkGeneratorContext.ts b/generators/java-v2/sdk/src/SdkGeneratorContext.ts index 956fb6c6f7fc..e2f6d630f73c 100644 --- a/generators/java-v2/sdk/src/SdkGeneratorContext.ts +++ b/generators/java-v2/sdk/src/SdkGeneratorContext.ts @@ -78,30 +78,29 @@ export class SdkGeneratorContext extends AbstractJavaGeneratorContext {}, builderImplTypeSpec::addField, - builderImplTypeSpec::addMethod); + builderImplTypeSpec::addMethod, + false); } else { addSimpleFieldSetter( enrichedProperty, nestedBuilderClassName, _unused -> {}, builderImplTypeSpec::addField, - builderImplTypeSpec::addMethod); + builderImplTypeSpec::addMethod, + false); } } @@ -498,14 +500,16 @@ private PoetTypeWithClassName buildFinal( finalStageClassName, finalStageBuilder::addMethod, builderImpl::addReversedFields, - builderImpl::addReversedMethods); + builderImpl::addReversedMethods, + true); } else { addSimpleFieldSetter( enrichedProperty, finalStageClassName, finalStageBuilder::addMethod, builderImpl::addReversedFields, - builderImpl::addReversedMethods); + builderImpl::addReversedMethods, + true); } } return PoetTypeWithClassName.of(finalStageClassName, finalStageBuilder.build()); @@ -1043,7 +1047,8 @@ private void addSimpleFieldSetter( ClassName returnClass, Consumer interfaceSetterConsumer, Consumer implFieldConsumer, - Consumer implSetterConsumer) { + Consumer implSetterConsumer, + boolean isOverridden) { FieldSpec fieldSpec = enrichedProperty.fieldSpec; TypeName poetTypeName = enrichedProperty.enrichedObjectProperty.poetTypeName(); @@ -1065,8 +1070,10 @@ private void addSimpleFieldSetter( MethodSpec.Builder implSetter = MethodSpec.methodBuilder(fieldSpec.name) .addModifiers(Modifier.PUBLIC) .returns(returnClass) - .addAnnotation(ClassName.get("", "java.lang.Override")) .addParameter(poetTypeName, fieldSpec.name); + if (isOverridden) { + implSetter.addAnnotation(ClassName.get("", "java.lang.Override")); + } if (enrichedProperty.enrichedObjectProperty.wireKey().isPresent() && !enrichedProperty.enrichedObjectProperty.wireKey().get().isEmpty()) { @@ -1095,7 +1102,8 @@ private void addNullableFieldSetter( ClassName returnClass, Consumer interfaceSetterConsumer, Consumer implFieldConsumer, - Consumer implSetterConsumer) { + Consumer implSetterConsumer, + boolean isOverridden) { FieldSpec fieldSpec = enrichedProperty.fieldSpec; TypeName poetTypeName = enrichedProperty.enrichedObjectProperty.poetTypeName(); @@ -1124,8 +1132,10 @@ private void addNullableFieldSetter( MethodSpec.Builder implSetter = MethodSpec.methodBuilder(fieldSpec.name) .addModifiers(Modifier.PUBLIC) - .returns(returnClass) - .addAnnotation(ClassName.get("", "java.lang.Override")); + .returns(returnClass); + if (isOverridden) { + implSetter.addAnnotation(ClassName.get("", "java.lang.Override")); + } implSetter.addParameter(paramBuilder.build()); diff --git a/generators/java/sdk/changes/4.10.3/fix-stream-parameter-response.yml b/generators/java/sdk/changes/4.10.3/fix-stream-parameter-response.yml new file mode 100644 index 000000000000..d22273922bfb --- /dev/null +++ b/generators/java/sdk/changes/4.10.3/fix-stream-parameter-response.yml @@ -0,0 +1,7 @@ +# yaml-language-server: $schema=../../../../../fern-changes-yml.schema.json + +- summary: | + Support endpoints whose streaming behavior is toggled by a request parameter + ("stream parameter"). The SDK now resolves the streaming response variant for + these endpoints instead of failing generation. + type: fix diff --git a/generators/java/sdk/changes/4.10.4/fix-optional-request-body-snippet.yml b/generators/java/sdk/changes/4.10.4/fix-optional-request-body-snippet.yml new file mode 100644 index 000000000000..52ae1d5f43fb --- /dev/null +++ b/generators/java/sdk/changes/4.10.4/fix-optional-request-body-snippet.yml @@ -0,0 +1,6 @@ +- summary: | + Fix dynamic snippet generation for endpoints with an optional request body + that wraps a nullable type (e.g. `optional>`). The snippet now + wraps the body in `Optional.of(...)` so it matches the generated client + method signature and compiles. + type: fix diff --git a/generators/java/sdk/changes/4.10.5/fix-nullable-optional-snippets.yml b/generators/java/sdk/changes/4.10.5/fix-nullable-optional-snippets.yml new file mode 100644 index 000000000000..87a784b2f42e --- /dev/null +++ b/generators/java/sdk/changes/4.10.5/fix-nullable-optional-snippets.yml @@ -0,0 +1,16 @@ +- summary: | + Fix Java SDK generation for the `use-nullable-annotation` and + `collapse-optional-nullable` configurations. + + - Dynamic snippets now honor these config flags when emitting nullable and + optional values, so a nullable property rendered as a raw (non-`Optional`) + value no longer produces type mismatches such as + `Email cannot be converted to Nullable`. + - Staged-builder method calls in snippets are now ordered correctly: required + stages first, then the final-stage (optional, nullable, and collection) + properties. Collections (`list`/`set`/`map`) are treated as final-stage + properties to match v1's staged builders. + - Builder setters on the default (non-staged) builder no longer emit a + spurious `@Override` annotation, which previously failed to compile for + nullable request properties (e.g. `FilterByRoleRequest`). + type: fix diff --git a/generators/java/sdk/changes/4.10.6/fix-inline-type-snippet-names.yml b/generators/java/sdk/changes/4.10.6/fix-inline-type-snippet-names.yml new file mode 100644 index 000000000000..9f6f221352f3 --- /dev/null +++ b/generators/java/sdk/changes/4.10.6/fix-inline-type-snippet-names.yml @@ -0,0 +1,8 @@ +# yaml-language-server: $schema=../../../../../fern-changes-yml.schema.json + +- summary: | + Fix dynamic snippet generation to reference the correct nested class names for inline + types. Inline types within objects, discriminated unions, and undiscriminated unions are + now resolved to their actual generated nested class (e.g. `Parent.Bar.Type1`) instead of a + mangled top-level name, so generated snippets compile. + type: fix diff --git a/generators/java/sdk/changes/4.10.7/fix-nullable-optional-snippet-generation.yml b/generators/java/sdk/changes/4.10.7/fix-nullable-optional-snippet-generation.yml new file mode 100644 index 000000000000..b670a3e08173 --- /dev/null +++ b/generators/java/sdk/changes/4.10.7/fix-nullable-optional-snippet-generation.yml @@ -0,0 +1,9 @@ +# yaml-language-server: $schema=../../../../../fern-changes-yml.schema.json + +- summary: | + Fixed nested optional/nullable type generation in code examples under + `collapse-optional-nullable`. The snippet type mapper now collapses nested + same-kind wrappers (`optional>`, `nullable>`) into a + single `OptionalNullable`, matching the literal mapper and avoiding + type/value mismatches in generated examples. + type: fix diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/endpoint/AbstractHttpResponseParserGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/endpoint/AbstractHttpResponseParserGenerator.java index e88f2dfbc69a..fe5984530bd3 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/endpoint/AbstractHttpResponseParserGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/endpoint/AbstractHttpResponseParserGenerator.java @@ -533,8 +533,7 @@ public com.fern.ir.model.types.TypeReference _visitUnknown(Object unknownType) { @Override public TypeName visitStreamParameter(StreamParameterResponse streamParameterResponse) { - // TODO: Implement stream parameters. - throw new UnsupportedOperationException("Not implemented."); + return visitStreaming(streamParameterResponse.getStreamResponse()); } @Override @@ -578,7 +577,7 @@ public Boolean visitStreaming(StreamingResponse streamingResponse) { @Override public Boolean visitStreamParameter(StreamParameterResponse streamParameterResponse) { - return false; + return true; } @Override @@ -667,8 +666,7 @@ public Void visitStreaming(StreamingResponse streamingResponse) { @Override public Void visitStreamParameter(StreamParameterResponse streamParameterResponse) { - // TODO: Implement stream parameters. - throw new UnsupportedOperationException("Not implemented."); + return visitStreaming(streamParameterResponse.getStreamResponse()); } @Override @@ -1052,8 +1050,7 @@ public CodeBlock _visitUnknown(Object unknownType) { @Override public Void visitStreamParameter(StreamParameterResponse streamParameterResponse) { - // TODO: Implement stream parameters. - throw new UnsupportedOperationException("Not implemented."); + return visitStreaming(streamParameterResponse.getStreamResponse()); } @Override diff --git a/generators/java/sdk/versions.yml b/generators/java/sdk/versions.yml index ae4c37ddd197..cf323405ecbb 100644 --- a/generators/java/sdk/versions.yml +++ b/generators/java/sdk/versions.yml @@ -1,4 +1,64 @@ # yaml-language-server: $schema=../../../fern-versions-yml.schema.json +- version: 4.10.7 + changelogEntry: + - summary: | + Fixed nested optional/nullable type generation in code examples under + `collapse-optional-nullable`. The snippet type mapper now collapses nested + same-kind wrappers (`optional>`, `nullable>`) into a + single `OptionalNullable`, matching the literal mapper and avoiding + type/value mismatches in generated examples. + type: fix + createdAt: "2026-06-18" + irVersion: 66 +- version: 4.10.6 + changelogEntry: + - summary: | + Fix dynamic snippet generation to reference the correct nested class names for inline + types. Inline types within objects, discriminated unions, and undiscriminated unions are + now resolved to their actual generated nested class (e.g. `Parent.Bar.Type1`) instead of a + mangled top-level name, so generated snippets compile. + type: fix + createdAt: "2026-06-18" + irVersion: 66 +- version: 4.10.5 + changelogEntry: + - summary: | + Fix Java SDK generation for the `use-nullable-annotation` and + `collapse-optional-nullable` configurations. + + - Dynamic snippets now honor these config flags when emitting nullable and + optional values, so a nullable property rendered as a raw (non-`Optional`) + value no longer produces type mismatches such as + `Email cannot be converted to Nullable`. + - Staged-builder method calls in snippets are now ordered correctly: required + stages first, then the final-stage (optional, nullable, and collection) + properties. Collections (`list`/`set`/`map`) are treated as final-stage + properties to match v1's staged builders. + - Builder setters on the default (non-staged) builder no longer emit a + spurious `@Override` annotation, which previously failed to compile for + nullable request properties (e.g. `FilterByRoleRequest`). + type: fix + createdAt: "2026-06-18" + irVersion: 66 +- version: 4.10.4 + changelogEntry: + - summary: | + Fix dynamic snippet generation for endpoints with an optional request body + that wraps a nullable type (e.g. `optional>`). The snippet now + wraps the body in `Optional.of(...)` so it matches the generated client + method signature and compiles. + type: fix + createdAt: "2026-06-18" + irVersion: 66 +- version: 4.10.3 + changelogEntry: + - summary: | + Support endpoints whose streaming behavior is toggled by a request parameter + ("stream parameter"). The SDK now resolves the streaming response variant for + these endpoints instead of failing generation. + type: fix + createdAt: "2026-06-18" + irVersion: 66 - version: 4.10.2 changelogEntry: - summary: | diff --git a/generators/swift/dynamic-snippets/src/EndpointSnippetGenerator.ts b/generators/swift/dynamic-snippets/src/EndpointSnippetGenerator.ts index f7bb8fcc6055..ddd46c628a43 100644 --- a/generators/swift/dynamic-snippets/src/EndpointSnippetGenerator.ts +++ b/generators/swift/dynamic-snippets/src/EndpointSnippetGenerator.ts @@ -469,22 +469,28 @@ export class EndpointSnippetGenerator { namedParameters: FernIr.dynamic.NamedParameter[]; snippet: FernIr.dynamic.EndpointSnippetRequest; }): swift.FunctionArgument[] { - return this.context - .getExampleObjectProperties({ - parameters: namedParameters, - snippetObject: snippet.pathParameters ?? {} - }) - .map((parameter) => { - return swift.functionArgument({ - label: parameter.name.name.camelCase.unsafeName, - // Generated Swift SDKs declare every path parameter as `String` in - // the endpoint method signature (the value is interpolated into the - // URL string), so render non-string primitive literals as their - // String representation here to keep the rendered snippet's - // argument type compatible with the SDK signature. - value: this.renderPathParameterValueAsSwiftString({ value: parameter.value }) - }); - }); + return ( + this.context + // Path parameters are always required arguments on the generated endpoint + // method, so synthesize a placeholder (e.g. ``) for any whose + // value is absent from the example. This notably covers path parameters bound + // to API-level variables, whose example values are not carried per-endpoint. + .associateByWireValueOrDefault({ + parameters: namedParameters, + values: snippet.pathParameters ?? {} + }) + .map((parameter) => { + return swift.functionArgument({ + label: parameter.name.name.camelCase.unsafeName, + // Generated Swift SDKs declare every path parameter as `String` in + // the endpoint method signature (the value is interpolated into the + // URL string), so render non-string primitive literals as their + // String representation here to keep the rendered snippet's + // argument type compatible with the SDK signature. + value: this.renderPathParameterValueAsSwiftString({ value: parameter.value }) + }); + }) + ); } private renderPathParameterValueAsSwiftString({ value }: { value: unknown }): swift.Expression { diff --git a/generators/swift/sdk/changes/0.35.16/fix-variable-path-parameter-snippets.yml b/generators/swift/sdk/changes/0.35.16/fix-variable-path-parameter-snippets.yml new file mode 100644 index 000000000000..2fe5293bfba8 --- /dev/null +++ b/generators/swift/sdk/changes/0.35.16/fix-variable-path-parameter-snippets.yml @@ -0,0 +1,7 @@ +- summary: | + Fix generated snippets and wire tests omitting path parameters bound to + API-level variables. Path parameters are always required arguments on the + generated endpoint method, so a placeholder value (e.g. ``) is + now emitted for any path parameter whose value is absent from the example, + keeping the generated SDK, snippets, and wire tests compiling. + type: fix diff --git a/generators/swift/sdk/versions.yml b/generators/swift/sdk/versions.yml index ece9b5b1b2d7..279ad9bfece4 100644 --- a/generators/swift/sdk/versions.yml +++ b/generators/swift/sdk/versions.yml @@ -1,4 +1,15 @@ # yaml-language-server: $schema=../../../fern-versions-yml.schema.json +- version: 0.35.16 + changelogEntry: + - summary: | + Fix generated snippets and wire tests omitting path parameters bound to + API-level variables. Path parameters are always required arguments on the + generated endpoint method, so a placeholder value (e.g. ``) is + now emitted for any path parameter whose value is absent from the example, + keeping the generated SDK, snippets, and wire tests compiling. + type: fix + createdAt: "2026-06-18" + irVersion: 66 - version: 0.35.15 changelogEntry: - summary: | diff --git a/packages/cli/cli/changes/5.50.2/retry-register-api-definition.yml b/packages/cli/cli/changes/5.50.2/retry-register-api-definition.yml new file mode 100644 index 000000000000..06bc5fa28481 --- /dev/null +++ b/packages/cli/cli/changes/5.50.2/retry-register-api-definition.yml @@ -0,0 +1,6 @@ +- summary: | + Add retry with exponential backoff to registerApiDefinition during docs + publish. Large docs sites (e.g. 30+ API versions) could hit transient + connection aborts from FDR; the CLI now retries up to 3 times with + 1 s / 2 s / 4 s delays before failing. + type: fix diff --git a/packages/cli/cli/versions.yml b/packages/cli/cli/versions.yml index 58e0f1d6a626..094d220056be 100644 --- a/packages/cli/cli/versions.yml +++ b/packages/cli/cli/versions.yml @@ -1,4 +1,14 @@ # yaml-language-server: $schema=../../../fern-versions-yml.schema.json +- version: 5.50.2 + changelogEntry: + - summary: | + Add retry with exponential backoff to registerApiDefinition during docs + publish. Large docs sites (e.g. 30+ API versions) could hit transient + connection aborts from FDR; the CLI now retries up to 3 times with + 1 s / 2 s / 4 s delays before failing. + type: fix + createdAt: "2026-06-18" + irVersion: 67 - version: 5.50.1 changelogEntry: - summary: | diff --git a/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/DynamicSnippetsTestGenerator.ts b/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/DynamicSnippetsTestGenerator.ts index d62a61b20899..015eeb962a67 100644 --- a/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/DynamicSnippetsTestGenerator.ts +++ b/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/DynamicSnippetsTestGenerator.ts @@ -19,7 +19,8 @@ interface DynamicSnippetsGenerator { new ( context: TaskContext, ir: dynamic.DynamicIntermediateRepresentation, - config: FernGeneratorExec.GeneratorConfig + config: FernGeneratorExec.GeneratorConfig, + inlineTypeIds?: Set ): { generateTests(params: { outputDir: AbsoluteFilePath; requests: DynamicSnippetsTestRequest[] }): Promise; }; @@ -68,7 +69,12 @@ export class DynamicSnippetsTestGenerator { this.context.logger.debug(`Skipping dynamic snippets test generation for language "${language}"`); return; } - return new config.generator(this.context, this.testSuite.ir, this.testSuite.config).generateTests({ + return new config.generator( + this.context, + this.testSuite.ir, + this.testSuite.config, + this.testSuite.inlineTypeIds + ).generateTests({ outputDir, requests: this.testSuite.requests }); diff --git a/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/DynamicSnippetsTestSuite.ts b/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/DynamicSnippetsTestSuite.ts index 8cd81092a458..ba951e229e94 100644 --- a/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/DynamicSnippetsTestSuite.ts +++ b/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/DynamicSnippetsTestSuite.ts @@ -11,4 +11,8 @@ export interface DynamicSnippetsTestSuite { ir: DynamicSnippets.DynamicIntermediateRepresentation; config: FernGeneratorExec.GeneratorConfig; requests: DynamicSnippetsTestRequest[]; + // Type IDs that the generator emits as inline (nested) classes. The dynamic IR does not carry + // the `inline` flag, so it is computed from the full IR and threaded through to the + // language-specific generators that need it to resolve nested class names. + inlineTypeIds: Set; } diff --git a/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/generateDynamicSnippetsTestSuite.ts b/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/generateDynamicSnippetsTestSuite.ts index 4fb1406f36f6..39fa5bcf0a7b 100644 --- a/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/generateDynamicSnippetsTestSuite.ts +++ b/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/generateDynamicSnippetsTestSuite.ts @@ -16,9 +16,15 @@ export async function generateDynamicSnippetsTestSuite({ code: CliError.Code.InternalError }); } + const inlineTypeIds = new Set( + Object.values(ir.types) + .filter((typeDeclaration) => typeDeclaration.inline === true) + .map((typeDeclaration) => typeDeclaration.name.typeId) + ); return { ir: ir.dynamic, config, + inlineTypeIds, requests: Object.entries(ir.dynamic.endpoints).flatMap(([endpointId, endpoint]) => (endpoint.examples ?? []).map((example) => ({ endpointId, diff --git a/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/java/DynamicSnippetsJavaTestGenerator.ts b/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/java/DynamicSnippetsJavaTestGenerator.ts index 8ab86e94ec26..f809ac682470 100644 --- a/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/java/DynamicSnippetsJavaTestGenerator.ts +++ b/packages/cli/generation/local-generation/local-workspace-runner/src/dynamic-snippets/java/DynamicSnippetsJavaTestGenerator.ts @@ -18,7 +18,8 @@ export class DynamicSnippetsJavaTestGenerator { constructor( private readonly context: TaskContext, private readonly ir: dynamic.DynamicIntermediateRepresentation, - private readonly generatorConfig: FernGeneratorExec.GeneratorConfig + private readonly generatorConfig: FernGeneratorExec.GeneratorConfig, + private readonly inlineTypeIds?: Set ) { // Note: the local-workspace-runner uses convertIr which always returns a DynamicIntermediateRepresentation // that is actually of the latest version in the workspace. @@ -35,7 +36,8 @@ export class DynamicSnippetsJavaTestGenerator { this.dynamicSnippetsGenerator = new DynamicSnippetsGenerator({ // biome-ignore lint/suspicious/noExplicitAny: workaround for version incompatibility - see note above ir: convertIr(this.ir) as unknown as any, - config: this.generatorConfig + config: this.generatorConfig, + inlineTypeIds: this.inlineTypeIds }); } diff --git a/packages/cli/generation/remote-generation/remote-workspace-runner/src/__test__/retryWithBackoff.test.ts b/packages/cli/generation/remote-generation/remote-workspace-runner/src/__test__/retryWithBackoff.test.ts new file mode 100644 index 000000000000..9098a66b532d --- /dev/null +++ b/packages/cli/generation/remote-generation/remote-workspace-runner/src/__test__/retryWithBackoff.test.ts @@ -0,0 +1,338 @@ +import { describe, expect, it, vi } from "vitest"; +import { retryWithBackoff } from "../retryWithBackoff.js"; + +function createMockLogger() { + return { + disable: vi.fn(), + enable: vi.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + log: vi.fn(), + trace: vi.fn() + }; +} + +const noDelay = async (_ms: number) => { + // no-op: skip delay in tests +}; + +describe("retryWithBackoff", () => { + it("should return the result when fn succeeds on first try", async () => { + const logger = createMockLogger(); + const result = await retryWithBackoff({ + fn: async () => "success", + maxRetries: 3, + baseDelayMs: 1000, + logger, + delayFn: noDelay + }); + expect(result).toBe("success"); + expect(logger.warn).not.toHaveBeenCalled(); + }); + + it("should retry and succeed after transient failures", async () => { + const logger = createMockLogger(); + let callCount = 0; + + const result = await retryWithBackoff({ + fn: async () => { + callCount++; + if (callCount <= 2) { + throw new Error("transient"); + } + return "recovered"; + }, + maxRetries: 3, + baseDelayMs: 1000, + logger, + label: "test-op", + delayFn: noDelay + }); + + expect(result).toBe("recovered"); + expect(callCount).toBe(3); + expect(logger.warn).toHaveBeenCalledTimes(2); + }); + + it("should throw after exhausting all retries", async () => { + const logger = createMockLogger(); + let callCount = 0; + + await expect( + retryWithBackoff({ + fn: async () => { + callCount++; + throw new Error("persistent failure"); + }, + maxRetries: 3, + baseDelayMs: 1000, + logger, + delayFn: noDelay + }) + ).rejects.toThrow("persistent failure"); + + // 1 initial + 3 retries = 4 total calls + expect(callCount).toBe(4); + }); + + it("should fail fast on non-retryable errors without retrying", async () => { + const logger = createMockLogger(); + let callCount = 0; + + const isRetryable = (error: unknown) => { + const err = error as Record; + return err.statusCode == null || (err.statusCode as number) >= 500; + }; + + await expect( + retryWithBackoff({ + fn: async () => { + callCount++; + const err = new Error("bad request") as Error & { statusCode: number }; + err.statusCode = 400; + throw err; + }, + maxRetries: 3, + baseDelayMs: 1000, + isRetryable, + logger, + delayFn: noDelay + }) + ).rejects.toThrow("bad request"); + + expect(callCount).toBe(1); + expect(logger.warn).not.toHaveBeenCalled(); + }); + + it("should retry on retryable errors determined by isRetryable", async () => { + const logger = createMockLogger(); + let callCount = 0; + + const isRetryable = (error: unknown) => { + const err = error as Record; + return (err.statusCode as number) >= 500; + }; + + await expect( + retryWithBackoff({ + fn: async () => { + callCount++; + const err = new Error("server error") as Error & { statusCode: number }; + err.statusCode = 502; + throw err; + }, + maxRetries: 2, + baseDelayMs: 1000, + isRetryable, + logger, + delayFn: noDelay + }) + ).rejects.toThrow("server error"); + + // 1 initial + 2 retries = 3 total calls + expect(callCount).toBe(3); + }); + + it("should use exponential backoff delays without jitter", async () => { + const logger = createMockLogger(); + const delays: number[] = []; + + await retryWithBackoff({ + fn: async () => { + throw new Error("fail"); + }, + maxRetries: 3, + baseDelayMs: 1000, + logger, + delayFn: async (ms: number) => { + delays.push(ms); + } + }).catch(() => { + // expected + }); + + // jitterFactor defaults to 0, so no jitter: + // Attempt 0: 1000 * 2^0 = 1000ms + // Attempt 1: 1000 * 2^1 = 2000ms + // Attempt 2: 1000 * 2^2 = 4000ms + expect(delays).toEqual([1000, 2000, 4000]); + }); + + it("should apply jitter when jitterFactor is set", async () => { + const logger = createMockLogger(); + const delays: number[] = []; + + // Mock Math.random to return 0.0 (minimum jitter: 1 + (0.0 - 0.5) * 0.5 = 0.75) + const originalRandom = Math.random; + Math.random = () => 0.0; + + try { + await retryWithBackoff({ + fn: async () => { + throw new Error("fail"); + }, + maxRetries: 3, + baseDelayMs: 1000, + jitterFactor: 0.5, + logger, + delayFn: async (ms: number) => { + delays.push(ms); + } + }).catch(() => { + // expected + }); + } finally { + Math.random = originalRandom; + } + + // jitter = 1 + (0.0 - 0.5) * 0.5 = 0.75 + // Attempt 0: round(1000 * 1 * 0.75) = 750ms + // Attempt 1: round(1000 * 2 * 0.75) = 1500ms + // Attempt 2: round(1000 * 4 * 0.75) = 3000ms + expect(delays).toEqual([750, 1500, 3000]); + }); + + it("should apply no jitter when Math.random returns 0.5", async () => { + const logger = createMockLogger(); + const delays: number[] = []; + + const originalRandom = Math.random; + Math.random = () => 0.5; + + try { + await retryWithBackoff({ + fn: async () => { + throw new Error("fail"); + }, + maxRetries: 3, + baseDelayMs: 1000, + jitterFactor: 0.5, + logger, + delayFn: async (ms: number) => { + delays.push(ms); + } + }).catch(() => { + // expected + }); + } finally { + Math.random = originalRandom; + } + + // jitter = 1 + (0.5 - 0.5) * 0.5 = 1.0 (no jitter) + expect(delays).toEqual([1000, 2000, 4000]); + }); + + it("should include label and attempt count in warn messages", async () => { + const logger = createMockLogger(); + let callCount = 0; + + await retryWithBackoff({ + fn: async () => { + callCount++; + if (callCount <= 2) { + throw new Error("fail"); + } + return "ok"; + }, + maxRetries: 3, + baseDelayMs: 1000, + logger, + label: "registerApiDefinition failed for my-api", + delayFn: noDelay + }); + + expect(logger.warn).toHaveBeenCalledTimes(2); + const firstCall = logger.warn.mock.calls[0]?.[0] as string; + const secondCall = logger.warn.mock.calls[1]?.[0] as string; + expect(firstCall).toContain("registerApiDefinition failed for my-api"); + expect(firstCall).toContain("attempt 1/4"); + expect(secondCall).toContain("attempt 2/4"); + }); + + it("should not log warnings when label is omitted", async () => { + const logger = createMockLogger(); + let callCount = 0; + + await retryWithBackoff({ + fn: async () => { + callCount++; + if (callCount <= 1) { + throw new Error("fail"); + } + return "ok"; + }, + maxRetries: 3, + baseDelayMs: 1000, + logger, + delayFn: noDelay + }); + + expect(logger.warn).not.toHaveBeenCalled(); + }); + + it("should work with maxRetries = 0 (no retries)", async () => { + const logger = createMockLogger(); + + await expect( + retryWithBackoff({ + fn: async () => { + throw new Error("immediate fail"); + }, + maxRetries: 0, + baseDelayMs: 1000, + logger, + delayFn: noDelay + }) + ).rejects.toThrow("immediate fail"); + }); + + it("should default isRetryable to always-retry", async () => { + const logger = createMockLogger(); + let callCount = 0; + + await retryWithBackoff({ + fn: async () => { + callCount++; + if (callCount <= 2) { + throw new Error("any error"); + } + return "ok"; + }, + maxRetries: 3, + baseDelayMs: 1000, + logger, + delayFn: noDelay + }); + + expect(callCount).toBe(3); + }); + + it("should pass the thrown error to isRetryable", async () => { + const logger = createMockLogger(); + const errorsSeenByIsRetryable: unknown[] = []; + + const sentinel = new Error("sentinel"); + + await retryWithBackoff({ + fn: async () => { + throw sentinel; + }, + maxRetries: 1, + baseDelayMs: 1000, + isRetryable: (error) => { + errorsSeenByIsRetryable.push(error); + return true; + }, + logger, + delayFn: noDelay + }).catch(() => { + // expected + }); + + expect(errorsSeenByIsRetryable).toHaveLength(2); + expect(errorsSeenByIsRetryable[0]).toBe(sentinel); + expect(errorsSeenByIsRetryable[1]).toBe(sentinel); + }); +}); diff --git a/packages/cli/generation/remote-generation/remote-workspace-runner/src/publishDocs.ts b/packages/cli/generation/remote-generation/remote-workspace-runner/src/publishDocs.ts index a95d7706e881..b6d4c586d06f 100644 --- a/packages/cli/generation/remote-generation/remote-workspace-runner/src/publishDocs.ts +++ b/packages/cli/generation/remote-generation/remote-workspace-runner/src/publishDocs.ts @@ -67,12 +67,17 @@ import { measureImageSizes } from "./measureImageSizes.js"; import { normalizeRepoUrlToHttps } from "./normalizeRepoUrl.js"; import { publishDocsViaLedger } from "./publishDocsLedger.js"; import { publishDocsViaLedgerPreview } from "./publishDocsLedgerPreview.js"; +import { retryWithBackoff } from "./retryWithBackoff.js"; import { asyncPool } from "./utils/asyncPool.js"; const MEASURE_IMAGE_BATCH_SIZE = 10; const UPLOAD_FILE_BATCH_SIZE = 10; const HASH_CONCURRENCY = parseInt(process.env.FERN_DOCS_ASSET_HASH_CONCURRENCY ?? "32", 10); +const REGISTER_MAX_RETRIES = 3; +const REGISTER_BASE_DELAY_MS = 1_000; +const REGISTER_JITTER_FACTOR = 0.5; + /** * Sanitizes a preview ID to be valid in a DNS subdomain label. * This MUST match the sanitizePreviewId in generateDocsWorkspace.ts and the @@ -445,13 +450,24 @@ export async function publishDocs({ } } + const effectiveApiName = apiName ?? getOriginalName(ir.apiName); + let response; try { - response = await fdr.api.register.registerApiDefinition({ - orgId: CjsFdrSdk.OrgId(organization), - apiId: CjsFdrSdk.ApiId(apiName ?? getOriginalName(ir.apiName)), - definition: apiDefinition, - dynamicIRs: dynamicIRsByLanguage + response = await retryWithBackoff({ + fn: () => + fdr.api.register.registerApiDefinition({ + orgId: CjsFdrSdk.OrgId(organization), + apiId: CjsFdrSdk.ApiId(effectiveApiName), + definition: apiDefinition, + dynamicIRs: dynamicIRsByLanguage + }), + maxRetries: REGISTER_MAX_RETRIES, + baseDelayMs: REGISTER_BASE_DELAY_MS, + jitterFactor: REGISTER_JITTER_FACTOR, + isRetryable: isTransientError, + logger: context.logger, + label: `registerApiDefinition failed for ${effectiveApiName}` }); } catch (error) { const errorDetails = extractErrorDetails(error); @@ -1975,6 +1991,22 @@ function getAIEnhancerConfig(withAiExamples: boolean, styleInstructions?: string }; } +/** + * Returns true when the error looks transient and is worth retrying + * (no HTTP status, 429, or 5xx). Fails fast on client errors like + * 400 (bad request), 401 (auth), 403 (forbidden). + */ +function isTransientError(error: unknown): boolean { + const errorObj = error as Record; + const content = errorObj?.content as Record | undefined; + const status = (errorObj?.statusCode ?? content?.statusCode) as number | undefined; + + if (status == null) { + return true; + } + return status === 429 || status >= 500; +} + /** * Extracts detailed error information from an FDR SDK error response. * This helps debug network/fetch failures by providing structured error details diff --git a/packages/cli/generation/remote-generation/remote-workspace-runner/src/retryWithBackoff.ts b/packages/cli/generation/remote-generation/remote-workspace-runner/src/retryWithBackoff.ts new file mode 100644 index 000000000000..5f4f0aa39345 --- /dev/null +++ b/packages/cli/generation/remote-generation/remote-workspace-runner/src/retryWithBackoff.ts @@ -0,0 +1,53 @@ +import { Logger } from "@fern-api/logger"; + +export interface RetryWithBackoffOptions { + fn: () => Promise; + maxRetries: number; + baseDelayMs: number; + jitterFactor?: number; + isRetryable?: (error: unknown) => boolean; + logger: Logger; + label?: string; + delayFn?: (ms: number) => Promise; +} + +/** + * Generic retry with exponential backoff and jitter. + * + * - Calls `fn` up to `maxRetries + 1` times. + * - Uses `isRetryable` to decide whether to retry (defaults to always-retry). + * - Applies exponential backoff with optional jitter between attempts. + * - Logs a warning before each retry when `label` is provided. + */ +export async function retryWithBackoff({ + fn, + maxRetries, + baseDelayMs, + jitterFactor = 0, + isRetryable = () => true, + logger, + label, + delayFn = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) +}: RetryWithBackoffOptions): Promise { + let lastError: unknown; + + for (let attempt = 0; attempt <= maxRetries; attempt++) { + try { + return await fn(); + } catch (error) { + lastError = error; + if (!isRetryable(error) || attempt >= maxRetries) { + throw error; + } + const jitter = jitterFactor > 0 ? 1 + (Math.random() - 0.5) * jitterFactor : 1; + const delayMs = Math.round(baseDelayMs * 2 ** attempt * jitter); + if (label != null) { + logger.warn(`${label} (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delayMs}ms...`); + } + await delayFn(delayMs); + } + } + + // Unreachable — the loop either returns or throws — but satisfies TypeScript. + throw lastError; +} diff --git a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/.fern/metadata.json b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/.fern/metadata.json index 21712e689624..ad728b0503a6 100644 --- a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/.fern/metadata.json +++ b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/.fern/metadata.json @@ -1,15 +1,14 @@ { "cliVersion": "DUMMY", "generatorName": "fernapi/fern-java-sdk", - "generatorVersion": "local", + "generatorVersion": "latest", "generatorConfig": { "enable-inline-types": true, "wrapped-aliases": false, "enable-forward-compatible-enums": true }, "originGitCommit": "DUMMY", - "invokedBy": "ci", + "invokedBy": "manual", "requestedVersion": "0.0.1", - "ciProvider": "github", "sdkVersion": "0.0.1" } \ No newline at end of file diff --git a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/README.md b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/README.md index 86424b10f1c0..e7504ea26589 100644 --- a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/README.md +++ b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/README.md @@ -57,7 +57,6 @@ package com.example.usage; import com.seed.object.SeedObjectClient; import com.seed.object.requests.PostRootRequest; -import com.seed.object.types.RequestTypeInlineType1; public class Example { public static void main(String[] args) { @@ -69,7 +68,7 @@ public class Example { PostRootRequest .builder() .bar( - RequestTypeInlineType1 + PostRootRequest.Bar .builder() .foo("foo") .build() diff --git a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/reference.md b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/reference.md index 094011b7619d..b967a094d60a 100644 --- a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/reference.md +++ b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/reference.md @@ -16,7 +16,7 @@ client.getRoot( PostRootRequest .builder() .bar( - RequestTypeInlineType1 + PostRootRequest.Bar .builder() .foo("foo") .build() @@ -75,12 +75,12 @@ client.getDiscriminatedUnion( GetDiscriminatedUnionRequest .builder() .bar( - DiscriminatedUnion1.type1( - DiscriminatedUnion1InlineType1 + GetDiscriminatedUnionRequest.Bar.type1( + GetDiscriminatedUnionRequest.Bar.Type1 .builder() .foo("foo") .bar( - DiscriminatedUnion1InlineType1InlineType1 + GetDiscriminatedUnionRequest.Bar.Type1.Bar_ .builder() .foo("foo") .ref( @@ -154,12 +154,12 @@ client.getUndiscriminatedUnion( GetUndiscriminatedUnionRequest .builder() .bar( - UndiscriminatedUnion1.of( - UndiscriminatedUnion1InlineType1 + GetUndiscriminatedUnionRequest.Bar.of( + GetUndiscriminatedUnionRequest.Bar.InlineType1 .builder() .foo("foo") .bar( - UndiscriminatedUnion1InlineType1InlineType1 + GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_ .builder() .foo("foo") .ref( diff --git a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/snippet.json b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/snippet.json index 60736cc4f4c6..ba37f66954b9 100644 --- a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/snippet.json +++ b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/snippet.json @@ -1,7 +1,7 @@ { "endpoints": [ { - "example_identifier": "eb26ffd5", + "example_identifier": "73e3485", "id": { "method": "POST", "path": "/root/root", @@ -9,12 +9,12 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\nimport com.seed.object.types.RequestTypeInlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n RequestTypeInlineType1\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\nimport com.seed.object.types.RequestTypeInlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n RequestTypeInlineType1\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n PostRootRequest.Bar\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n PostRootRequest.Bar\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" } }, { - "example_identifier": "78d1533c", + "example_identifier": "9516a5ec", "id": { "method": "POST", "path": "/root/discriminated-union", @@ -22,12 +22,12 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.DiscriminatedUnion1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1InlineType1;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n DiscriminatedUnion1.type1(\n DiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n DiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.DiscriminatedUnion1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1InlineType1;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n DiscriminatedUnion1.type1(\n DiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n DiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n GetDiscriminatedUnionRequest.Bar.type1(\n GetDiscriminatedUnionRequest.Bar.Type1\n .builder()\n .foo(\"foo\")\n .bar(\n GetDiscriminatedUnionRequest.Bar.Type1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n GetDiscriminatedUnionRequest.Bar.type1(\n GetDiscriminatedUnionRequest.Bar.Type1\n .builder()\n .foo(\"foo\")\n .bar(\n GetDiscriminatedUnionRequest.Bar.Type1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" } }, { - "example_identifier": "2c877e92", + "example_identifier": "37cb5902", "id": { "method": "POST", "path": "/root/undiscriminated-union", @@ -35,12 +35,12 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\nimport com.seed.object.types.UndiscriminatedUnion1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1InlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n UndiscriminatedUnion1.of(\n UndiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n UndiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\nimport com.seed.object.types.UndiscriminatedUnion1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1InlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n UndiscriminatedUnion1.of(\n UndiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n UndiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n GetUndiscriminatedUnionRequest.Bar.of(\n GetUndiscriminatedUnionRequest.Bar.InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n GetUndiscriminatedUnionRequest.Bar.of(\n GetUndiscriminatedUnionRequest.Bar.InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" } }, { - "example_identifier": "1fec8a00", + "example_identifier": "bbccdaf0", "id": { "method": "GET", "path": "/root/map-response", @@ -53,7 +53,7 @@ } }, { - "example_identifier": "993d4080", + "example_identifier": "daa48610", "id": { "method": "GET", "path": "/root/shared-child", @@ -66,7 +66,7 @@ } }, { - "example_identifier": "dfe68f2b", + "example_identifier": "84cf4e9b", "id": { "method": "GET", "path": "/root/orphan-parent", diff --git a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example0.java b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example0.java index a6b9bb19d983..73b0db15a4f4 100644 --- a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example0.java +++ b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example0.java @@ -2,7 +2,6 @@ import com.seed.object.SeedObjectClient; import com.seed.object.requests.PostRootRequest; -import com.seed.object.types.RequestTypeInlineType1; public class Example0 { public static void main(String[] args) { @@ -10,7 +9,7 @@ public static void main(String[] args) { SeedObjectClient.builder().url("https://api.fern.com").build(); client.getRoot(PostRootRequest.builder() - .bar(RequestTypeInlineType1.builder().foo("foo").build()) + .bar(PostRootRequest.Bar.builder().foo("foo").build()) .foo("foo") .build()); } diff --git a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example1.java b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example1.java index 0ef09b0552d8..fb06df48d260 100644 --- a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example1.java +++ b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example1.java @@ -2,9 +2,6 @@ import com.seed.object.SeedObjectClient; import com.seed.object.requests.GetDiscriminatedUnionRequest; -import com.seed.object.types.DiscriminatedUnion1; -import com.seed.object.types.DiscriminatedUnion1InlineType1; -import com.seed.object.types.DiscriminatedUnion1InlineType1InlineType1; import com.seed.object.types.ReferenceType; public class Example1 { @@ -13,9 +10,9 @@ public static void main(String[] args) { SeedObjectClient.builder().url("https://api.fern.com").build(); client.getDiscriminatedUnion(GetDiscriminatedUnionRequest.builder() - .bar(DiscriminatedUnion1.type1(DiscriminatedUnion1InlineType1.builder() + .bar(GetDiscriminatedUnionRequest.Bar.type1(GetDiscriminatedUnionRequest.Bar.Type1.builder() .foo("foo") - .bar(DiscriminatedUnion1InlineType1InlineType1.builder() + .bar(GetDiscriminatedUnionRequest.Bar.Type1.Bar_.builder() .foo("foo") .ref(ReferenceType.builder().foo("foo").build()) .build()) diff --git a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example2.java b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example2.java index 60a5aaa43c1f..4035ca8efd89 100644 --- a/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example2.java +++ b/seed/java-sdk/java-inline-types/enable-forward-compatible-enums/src/main/java/com/snippets/Example2.java @@ -3,9 +3,6 @@ import com.seed.object.SeedObjectClient; import com.seed.object.requests.GetUndiscriminatedUnionRequest; import com.seed.object.types.ReferenceType; -import com.seed.object.types.UndiscriminatedUnion1; -import com.seed.object.types.UndiscriminatedUnion1InlineType1; -import com.seed.object.types.UndiscriminatedUnion1InlineType1InlineType1; public class Example2 { public static void main(String[] args) { @@ -13,9 +10,9 @@ public static void main(String[] args) { SeedObjectClient.builder().url("https://api.fern.com").build(); client.getUndiscriminatedUnion(GetUndiscriminatedUnionRequest.builder() - .bar(UndiscriminatedUnion1.of(UndiscriminatedUnion1InlineType1.builder() + .bar(GetUndiscriminatedUnionRequest.Bar.of(GetUndiscriminatedUnionRequest.Bar.InlineType1.builder() .foo("foo") - .bar(UndiscriminatedUnion1InlineType1InlineType1.builder() + .bar(GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_.builder() .foo("foo") .ref(ReferenceType.builder().foo("foo").build()) .build()) diff --git a/seed/java-sdk/java-inline-types/inline/.fern/metadata.json b/seed/java-sdk/java-inline-types/inline/.fern/metadata.json index 0f44e5e37848..5a00f2c8ab4e 100644 --- a/seed/java-sdk/java-inline-types/inline/.fern/metadata.json +++ b/seed/java-sdk/java-inline-types/inline/.fern/metadata.json @@ -1,14 +1,13 @@ { "cliVersion": "DUMMY", "generatorName": "fernapi/fern-java-sdk", - "generatorVersion": "local", + "generatorVersion": "latest", "generatorConfig": { "enable-inline-types": true, "wrapped-aliases": true }, "originGitCommit": "DUMMY", - "invokedBy": "ci", + "invokedBy": "manual", "requestedVersion": "0.0.1", - "ciProvider": "github", "sdkVersion": "0.0.1" } \ No newline at end of file diff --git a/seed/java-sdk/java-inline-types/inline/README.md b/seed/java-sdk/java-inline-types/inline/README.md index 86424b10f1c0..e7504ea26589 100644 --- a/seed/java-sdk/java-inline-types/inline/README.md +++ b/seed/java-sdk/java-inline-types/inline/README.md @@ -57,7 +57,6 @@ package com.example.usage; import com.seed.object.SeedObjectClient; import com.seed.object.requests.PostRootRequest; -import com.seed.object.types.RequestTypeInlineType1; public class Example { public static void main(String[] args) { @@ -69,7 +68,7 @@ public class Example { PostRootRequest .builder() .bar( - RequestTypeInlineType1 + PostRootRequest.Bar .builder() .foo("foo") .build() diff --git a/seed/java-sdk/java-inline-types/inline/reference.md b/seed/java-sdk/java-inline-types/inline/reference.md index 094011b7619d..b967a094d60a 100644 --- a/seed/java-sdk/java-inline-types/inline/reference.md +++ b/seed/java-sdk/java-inline-types/inline/reference.md @@ -16,7 +16,7 @@ client.getRoot( PostRootRequest .builder() .bar( - RequestTypeInlineType1 + PostRootRequest.Bar .builder() .foo("foo") .build() @@ -75,12 +75,12 @@ client.getDiscriminatedUnion( GetDiscriminatedUnionRequest .builder() .bar( - DiscriminatedUnion1.type1( - DiscriminatedUnion1InlineType1 + GetDiscriminatedUnionRequest.Bar.type1( + GetDiscriminatedUnionRequest.Bar.Type1 .builder() .foo("foo") .bar( - DiscriminatedUnion1InlineType1InlineType1 + GetDiscriminatedUnionRequest.Bar.Type1.Bar_ .builder() .foo("foo") .ref( @@ -154,12 +154,12 @@ client.getUndiscriminatedUnion( GetUndiscriminatedUnionRequest .builder() .bar( - UndiscriminatedUnion1.of( - UndiscriminatedUnion1InlineType1 + GetUndiscriminatedUnionRequest.Bar.of( + GetUndiscriminatedUnionRequest.Bar.InlineType1 .builder() .foo("foo") .bar( - UndiscriminatedUnion1InlineType1InlineType1 + GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_ .builder() .foo("foo") .ref( diff --git a/seed/java-sdk/java-inline-types/inline/snippet.json b/seed/java-sdk/java-inline-types/inline/snippet.json index 60736cc4f4c6..ba37f66954b9 100644 --- a/seed/java-sdk/java-inline-types/inline/snippet.json +++ b/seed/java-sdk/java-inline-types/inline/snippet.json @@ -1,7 +1,7 @@ { "endpoints": [ { - "example_identifier": "eb26ffd5", + "example_identifier": "73e3485", "id": { "method": "POST", "path": "/root/root", @@ -9,12 +9,12 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\nimport com.seed.object.types.RequestTypeInlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n RequestTypeInlineType1\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\nimport com.seed.object.types.RequestTypeInlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n RequestTypeInlineType1\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n PostRootRequest.Bar\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n PostRootRequest.Bar\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" } }, { - "example_identifier": "78d1533c", + "example_identifier": "9516a5ec", "id": { "method": "POST", "path": "/root/discriminated-union", @@ -22,12 +22,12 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.DiscriminatedUnion1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1InlineType1;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n DiscriminatedUnion1.type1(\n DiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n DiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.DiscriminatedUnion1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1InlineType1;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n DiscriminatedUnion1.type1(\n DiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n DiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n GetDiscriminatedUnionRequest.Bar.type1(\n GetDiscriminatedUnionRequest.Bar.Type1\n .builder()\n .foo(\"foo\")\n .bar(\n GetDiscriminatedUnionRequest.Bar.Type1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n GetDiscriminatedUnionRequest.Bar.type1(\n GetDiscriminatedUnionRequest.Bar.Type1\n .builder()\n .foo(\"foo\")\n .bar(\n GetDiscriminatedUnionRequest.Bar.Type1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" } }, { - "example_identifier": "2c877e92", + "example_identifier": "37cb5902", "id": { "method": "POST", "path": "/root/undiscriminated-union", @@ -35,12 +35,12 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\nimport com.seed.object.types.UndiscriminatedUnion1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1InlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n UndiscriminatedUnion1.of(\n UndiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n UndiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\nimport com.seed.object.types.UndiscriminatedUnion1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1InlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n UndiscriminatedUnion1.of(\n UndiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n UndiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n GetUndiscriminatedUnionRequest.Bar.of(\n GetUndiscriminatedUnionRequest.Bar.InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n GetUndiscriminatedUnionRequest.Bar.of(\n GetUndiscriminatedUnionRequest.Bar.InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" } }, { - "example_identifier": "1fec8a00", + "example_identifier": "bbccdaf0", "id": { "method": "GET", "path": "/root/map-response", @@ -53,7 +53,7 @@ } }, { - "example_identifier": "993d4080", + "example_identifier": "daa48610", "id": { "method": "GET", "path": "/root/shared-child", @@ -66,7 +66,7 @@ } }, { - "example_identifier": "dfe68f2b", + "example_identifier": "84cf4e9b", "id": { "method": "GET", "path": "/root/orphan-parent", diff --git a/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example0.java b/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example0.java index a6b9bb19d983..73b0db15a4f4 100644 --- a/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example0.java +++ b/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example0.java @@ -2,7 +2,6 @@ import com.seed.object.SeedObjectClient; import com.seed.object.requests.PostRootRequest; -import com.seed.object.types.RequestTypeInlineType1; public class Example0 { public static void main(String[] args) { @@ -10,7 +9,7 @@ public static void main(String[] args) { SeedObjectClient.builder().url("https://api.fern.com").build(); client.getRoot(PostRootRequest.builder() - .bar(RequestTypeInlineType1.builder().foo("foo").build()) + .bar(PostRootRequest.Bar.builder().foo("foo").build()) .foo("foo") .build()); } diff --git a/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example1.java b/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example1.java index 0ef09b0552d8..fb06df48d260 100644 --- a/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example1.java +++ b/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example1.java @@ -2,9 +2,6 @@ import com.seed.object.SeedObjectClient; import com.seed.object.requests.GetDiscriminatedUnionRequest; -import com.seed.object.types.DiscriminatedUnion1; -import com.seed.object.types.DiscriminatedUnion1InlineType1; -import com.seed.object.types.DiscriminatedUnion1InlineType1InlineType1; import com.seed.object.types.ReferenceType; public class Example1 { @@ -13,9 +10,9 @@ public static void main(String[] args) { SeedObjectClient.builder().url("https://api.fern.com").build(); client.getDiscriminatedUnion(GetDiscriminatedUnionRequest.builder() - .bar(DiscriminatedUnion1.type1(DiscriminatedUnion1InlineType1.builder() + .bar(GetDiscriminatedUnionRequest.Bar.type1(GetDiscriminatedUnionRequest.Bar.Type1.builder() .foo("foo") - .bar(DiscriminatedUnion1InlineType1InlineType1.builder() + .bar(GetDiscriminatedUnionRequest.Bar.Type1.Bar_.builder() .foo("foo") .ref(ReferenceType.builder().foo("foo").build()) .build()) diff --git a/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example2.java b/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example2.java index 60a5aaa43c1f..4035ca8efd89 100644 --- a/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example2.java +++ b/seed/java-sdk/java-inline-types/inline/src/main/java/com/snippets/Example2.java @@ -3,9 +3,6 @@ import com.seed.object.SeedObjectClient; import com.seed.object.requests.GetUndiscriminatedUnionRequest; import com.seed.object.types.ReferenceType; -import com.seed.object.types.UndiscriminatedUnion1; -import com.seed.object.types.UndiscriminatedUnion1InlineType1; -import com.seed.object.types.UndiscriminatedUnion1InlineType1InlineType1; public class Example2 { public static void main(String[] args) { @@ -13,9 +10,9 @@ public static void main(String[] args) { SeedObjectClient.builder().url("https://api.fern.com").build(); client.getUndiscriminatedUnion(GetUndiscriminatedUnionRequest.builder() - .bar(UndiscriminatedUnion1.of(UndiscriminatedUnion1InlineType1.builder() + .bar(GetUndiscriminatedUnionRequest.Bar.of(GetUndiscriminatedUnionRequest.Bar.InlineType1.builder() .foo("foo") - .bar(UndiscriminatedUnion1InlineType1InlineType1.builder() + .bar(GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_.builder() .foo("foo") .ref(ReferenceType.builder().foo("foo").build()) .build()) diff --git a/seed/java-sdk/java-inline-types/no-wrapped-aliases/.fern/metadata.json b/seed/java-sdk/java-inline-types/no-wrapped-aliases/.fern/metadata.json index f7f759d72f16..3e560268b45c 100644 --- a/seed/java-sdk/java-inline-types/no-wrapped-aliases/.fern/metadata.json +++ b/seed/java-sdk/java-inline-types/no-wrapped-aliases/.fern/metadata.json @@ -1,14 +1,13 @@ { "cliVersion": "DUMMY", "generatorName": "fernapi/fern-java-sdk", - "generatorVersion": "local", + "generatorVersion": "latest", "generatorConfig": { "enable-inline-types": true, "wrapped-aliases": false }, "originGitCommit": "DUMMY", - "invokedBy": "ci", + "invokedBy": "manual", "requestedVersion": "0.0.1", - "ciProvider": "github", "sdkVersion": "0.0.1" } \ No newline at end of file diff --git a/seed/java-sdk/java-inline-types/no-wrapped-aliases/README.md b/seed/java-sdk/java-inline-types/no-wrapped-aliases/README.md index 86424b10f1c0..e7504ea26589 100644 --- a/seed/java-sdk/java-inline-types/no-wrapped-aliases/README.md +++ b/seed/java-sdk/java-inline-types/no-wrapped-aliases/README.md @@ -57,7 +57,6 @@ package com.example.usage; import com.seed.object.SeedObjectClient; import com.seed.object.requests.PostRootRequest; -import com.seed.object.types.RequestTypeInlineType1; public class Example { public static void main(String[] args) { @@ -69,7 +68,7 @@ public class Example { PostRootRequest .builder() .bar( - RequestTypeInlineType1 + PostRootRequest.Bar .builder() .foo("foo") .build() diff --git a/seed/java-sdk/java-inline-types/no-wrapped-aliases/reference.md b/seed/java-sdk/java-inline-types/no-wrapped-aliases/reference.md index 094011b7619d..b967a094d60a 100644 --- a/seed/java-sdk/java-inline-types/no-wrapped-aliases/reference.md +++ b/seed/java-sdk/java-inline-types/no-wrapped-aliases/reference.md @@ -16,7 +16,7 @@ client.getRoot( PostRootRequest .builder() .bar( - RequestTypeInlineType1 + PostRootRequest.Bar .builder() .foo("foo") .build() @@ -75,12 +75,12 @@ client.getDiscriminatedUnion( GetDiscriminatedUnionRequest .builder() .bar( - DiscriminatedUnion1.type1( - DiscriminatedUnion1InlineType1 + GetDiscriminatedUnionRequest.Bar.type1( + GetDiscriminatedUnionRequest.Bar.Type1 .builder() .foo("foo") .bar( - DiscriminatedUnion1InlineType1InlineType1 + GetDiscriminatedUnionRequest.Bar.Type1.Bar_ .builder() .foo("foo") .ref( @@ -154,12 +154,12 @@ client.getUndiscriminatedUnion( GetUndiscriminatedUnionRequest .builder() .bar( - UndiscriminatedUnion1.of( - UndiscriminatedUnion1InlineType1 + GetUndiscriminatedUnionRequest.Bar.of( + GetUndiscriminatedUnionRequest.Bar.InlineType1 .builder() .foo("foo") .bar( - UndiscriminatedUnion1InlineType1InlineType1 + GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_ .builder() .foo("foo") .ref( diff --git a/seed/java-sdk/java-inline-types/no-wrapped-aliases/snippet.json b/seed/java-sdk/java-inline-types/no-wrapped-aliases/snippet.json index 60736cc4f4c6..ba37f66954b9 100644 --- a/seed/java-sdk/java-inline-types/no-wrapped-aliases/snippet.json +++ b/seed/java-sdk/java-inline-types/no-wrapped-aliases/snippet.json @@ -1,7 +1,7 @@ { "endpoints": [ { - "example_identifier": "eb26ffd5", + "example_identifier": "73e3485", "id": { "method": "POST", "path": "/root/root", @@ -9,12 +9,12 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\nimport com.seed.object.types.RequestTypeInlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n RequestTypeInlineType1\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\nimport com.seed.object.types.RequestTypeInlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n RequestTypeInlineType1\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n PostRootRequest.Bar\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.PostRootRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getRoot(\n PostRootRequest\n .builder()\n .bar(\n PostRootRequest.Bar\n .builder()\n .foo(\"foo\")\n .build()\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" } }, { - "example_identifier": "78d1533c", + "example_identifier": "9516a5ec", "id": { "method": "POST", "path": "/root/discriminated-union", @@ -22,12 +22,12 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.DiscriminatedUnion1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1InlineType1;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n DiscriminatedUnion1.type1(\n DiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n DiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.DiscriminatedUnion1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1;\nimport com.seed.object.types.DiscriminatedUnion1InlineType1InlineType1;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n DiscriminatedUnion1.type1(\n DiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n DiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n GetDiscriminatedUnionRequest.Bar.type1(\n GetDiscriminatedUnionRequest.Bar.Type1\n .builder()\n .foo(\"foo\")\n .bar(\n GetDiscriminatedUnionRequest.Bar.Type1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetDiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getDiscriminatedUnion(\n GetDiscriminatedUnionRequest\n .builder()\n .bar(\n GetDiscriminatedUnionRequest.Bar.type1(\n GetDiscriminatedUnionRequest.Bar.Type1\n .builder()\n .foo(\"foo\")\n .bar(\n GetDiscriminatedUnionRequest.Bar.Type1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" } }, { - "example_identifier": "2c877e92", + "example_identifier": "37cb5902", "id": { "method": "POST", "path": "/root/undiscriminated-union", @@ -35,12 +35,12 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\nimport com.seed.object.types.UndiscriminatedUnion1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1InlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n UndiscriminatedUnion1.of(\n UndiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n UndiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\nimport com.seed.object.types.UndiscriminatedUnion1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1;\nimport com.seed.object.types.UndiscriminatedUnion1InlineType1InlineType1;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n UndiscriminatedUnion1.of(\n UndiscriminatedUnion1InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n UndiscriminatedUnion1InlineType1InlineType1\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n GetUndiscriminatedUnionRequest.Bar.of(\n GetUndiscriminatedUnionRequest.Bar.InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.object.SeedObjectClient;\nimport com.seed.object.requests.GetUndiscriminatedUnionRequest;\nimport com.seed.object.types.ReferenceType;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectClient client = SeedObjectClient\n .builder()\n .build();\n\n client.getUndiscriminatedUnion(\n GetUndiscriminatedUnionRequest\n .builder()\n .bar(\n GetUndiscriminatedUnionRequest.Bar.of(\n GetUndiscriminatedUnionRequest.Bar.InlineType1\n .builder()\n .foo(\"foo\")\n .bar(\n GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_\n .builder()\n .foo(\"foo\")\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n .ref(\n ReferenceType\n .builder()\n .foo(\"foo\")\n .build()\n )\n .build()\n )\n )\n .foo(\"foo\")\n .build()\n );\n }\n}\n" } }, { - "example_identifier": "1fec8a00", + "example_identifier": "bbccdaf0", "id": { "method": "GET", "path": "/root/map-response", @@ -53,7 +53,7 @@ } }, { - "example_identifier": "993d4080", + "example_identifier": "daa48610", "id": { "method": "GET", "path": "/root/shared-child", @@ -66,7 +66,7 @@ } }, { - "example_identifier": "dfe68f2b", + "example_identifier": "84cf4e9b", "id": { "method": "GET", "path": "/root/orphan-parent", diff --git a/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example0.java b/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example0.java index a6b9bb19d983..73b0db15a4f4 100644 --- a/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example0.java +++ b/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example0.java @@ -2,7 +2,6 @@ import com.seed.object.SeedObjectClient; import com.seed.object.requests.PostRootRequest; -import com.seed.object.types.RequestTypeInlineType1; public class Example0 { public static void main(String[] args) { @@ -10,7 +9,7 @@ public static void main(String[] args) { SeedObjectClient.builder().url("https://api.fern.com").build(); client.getRoot(PostRootRequest.builder() - .bar(RequestTypeInlineType1.builder().foo("foo").build()) + .bar(PostRootRequest.Bar.builder().foo("foo").build()) .foo("foo") .build()); } diff --git a/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example1.java b/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example1.java index 0ef09b0552d8..fb06df48d260 100644 --- a/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example1.java +++ b/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example1.java @@ -2,9 +2,6 @@ import com.seed.object.SeedObjectClient; import com.seed.object.requests.GetDiscriminatedUnionRequest; -import com.seed.object.types.DiscriminatedUnion1; -import com.seed.object.types.DiscriminatedUnion1InlineType1; -import com.seed.object.types.DiscriminatedUnion1InlineType1InlineType1; import com.seed.object.types.ReferenceType; public class Example1 { @@ -13,9 +10,9 @@ public static void main(String[] args) { SeedObjectClient.builder().url("https://api.fern.com").build(); client.getDiscriminatedUnion(GetDiscriminatedUnionRequest.builder() - .bar(DiscriminatedUnion1.type1(DiscriminatedUnion1InlineType1.builder() + .bar(GetDiscriminatedUnionRequest.Bar.type1(GetDiscriminatedUnionRequest.Bar.Type1.builder() .foo("foo") - .bar(DiscriminatedUnion1InlineType1InlineType1.builder() + .bar(GetDiscriminatedUnionRequest.Bar.Type1.Bar_.builder() .foo("foo") .ref(ReferenceType.builder().foo("foo").build()) .build()) diff --git a/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example2.java b/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example2.java index 60a5aaa43c1f..4035ca8efd89 100644 --- a/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example2.java +++ b/seed/java-sdk/java-inline-types/no-wrapped-aliases/src/main/java/com/snippets/Example2.java @@ -3,9 +3,6 @@ import com.seed.object.SeedObjectClient; import com.seed.object.requests.GetUndiscriminatedUnionRequest; import com.seed.object.types.ReferenceType; -import com.seed.object.types.UndiscriminatedUnion1; -import com.seed.object.types.UndiscriminatedUnion1InlineType1; -import com.seed.object.types.UndiscriminatedUnion1InlineType1InlineType1; public class Example2 { public static void main(String[] args) { @@ -13,9 +10,9 @@ public static void main(String[] args) { SeedObjectClient.builder().url("https://api.fern.com").build(); client.getUndiscriminatedUnion(GetUndiscriminatedUnionRequest.builder() - .bar(UndiscriminatedUnion1.of(UndiscriminatedUnion1InlineType1.builder() + .bar(GetUndiscriminatedUnionRequest.Bar.of(GetUndiscriminatedUnionRequest.Bar.InlineType1.builder() .foo("foo") - .bar(UndiscriminatedUnion1InlineType1InlineType1.builder() + .bar(GetUndiscriminatedUnionRequest.Bar.InlineType1.Bar_.builder() .foo("foo") .ref(ReferenceType.builder().foo("foo").build()) .build()) diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/README.md b/seed/java-sdk/nullable-optional/collapse-optional-nullable/README.md index 55727ead8e0b..c4a9dbf047ac 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/README.md +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/README.md @@ -70,24 +70,30 @@ public class Example { CreateUserRequest .builder() .username("username") + .email( + OptionalNullable.of("email") + ) + .phone("phone") .address( OptionalNullable.of( Address .builder() .street("street") .zipCode("zipCode") + .city( + OptionalNullable.of("city") + ) + .state("state") .country( OptionalNullable.of("country") ) - .city("city") - .state("state") - .buildingId("buildingId") + .buildingId( + OptionalNullable.of("buildingId") + ) .tenantId("tenantId") .build() ) ) - .email("email") - .phone("phone") .build() ); } diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/reference.md b/seed/java-sdk/nullable-optional/collapse-optional-nullable/reference.md index b7cdbf4e7cc8..b4c0c3d1582b 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/reference.md +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/reference.md @@ -85,24 +85,30 @@ client.nullableOptional().createUser( CreateUserRequest .builder() .username("username") + .email( + OptionalNullable.of("email") + ) + .phone("phone") .address( OptionalNullable.of( Address .builder() .street("street") .zipCode("zipCode") + .city( + OptionalNullable.of("city") + ) + .state("state") .country( OptionalNullable.of("country") ) - .city("city") - .state("state") - .buildingId("buildingId") + .buildingId( + OptionalNullable.of("buildingId") + ) .tenantId("tenantId") .build() ) ) - .email("email") - .phone("phone") .build() ); ``` @@ -171,12 +177,16 @@ client.nullableOptional().updateUser( .builder() .street("street") .zipCode("zipCode") + .city( + OptionalNullable.of("city") + ) + .state("state") .country( OptionalNullable.of("country") ) - .city("city") - .state("state") - .buildingId("buildingId") + .buildingId( + OptionalNullable.of("buildingId") + ) .tenantId("tenantId") .build() ) @@ -338,10 +348,12 @@ client.nullableOptional().searchUsers( SearchUsersRequest .builder() .query("query") + .department( + OptionalNullable.of("department") + ) .isActive( OptionalNullable.of(true) ) - .department("department") .role("role") .build() ); @@ -426,13 +438,21 @@ client.nullableOptional().createComplexProfile( ComplexProfile .builder() .id("id") + .nullableRole( + OptionalNullable.of(UserRole.ADMIN) + ) + .optionalRole(UserRole.ADMIN) .optionalNullableRole( OptionalNullable.of(UserRole.ADMIN) ) + .nullableStatus( + OptionalNullable.of(UserStatus.ACTIVE) + ) + .optionalStatus(UserStatus.ACTIVE) .optionalNullableStatus( OptionalNullable.of(UserStatus.ACTIVE) ) - .optionalNullableNotification( + .nullableNotification( OptionalNullable.of( NotificationMethod.email( EmailNotification @@ -444,16 +464,7 @@ client.nullableOptional().createComplexProfile( ) ) ) - .optionalNullableArray( - OptionalNullable.of( - Arrays.asList("optionalNullableArray", "optionalNullableArray") - ) - ) - .nullableRole(UserRole.ADMIN) - .optionalRole(UserRole.ADMIN) - .nullableStatus(UserStatus.ACTIVE) - .optionalStatus(UserStatus.ACTIVE) - .nullableNotification( + .optionalNotification( NotificationMethod.email( EmailNotification .builder() @@ -463,41 +474,53 @@ client.nullableOptional().createComplexProfile( .build() ) ) - .optionalNotification( - NotificationMethod.email( - EmailNotification - .builder() - .emailAddress("emailAddress") - .subject("subject") - .htmlContent("htmlContent") - .build() + .optionalNullableNotification( + OptionalNullable.of( + NotificationMethod.email( + EmailNotification + .builder() + .emailAddress("emailAddress") + .subject("subject") + .htmlContent("htmlContent") + .build() + ) ) ) .nullableSearchResult( - SearchResult.user( - UserResponse - .builder() - .id("id") - .username("username") - .createdAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) - .email("email") - .phone("phone") - .updatedAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) - .address( - Address - .builder() - .street("street") - .zipCode("zipCode") - .country( - OptionalNullable.of("country") - ) - .city("city") - .state("state") - .buildingId("buildingId") - .tenantId("tenantId") - .build() - ) - .build() + OptionalNullable.of( + SearchResult.user( + UserResponse + .builder() + .id("id") + .username("username") + .createdAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + .email( + OptionalNullable.of("email") + ) + .phone("phone") + .updatedAt( + OptionalNullable.of(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + ) + .address( + Address + .builder() + .street("street") + .zipCode("zipCode") + .city( + OptionalNullable.of("city") + ) + .state("state") + .country( + OptionalNullable.of("country") + ) + .buildingId( + OptionalNullable.of("buildingId") + ) + .tenantId("tenantId") + .build() + ) + .build() + ) ) ) .optionalSearchResult( @@ -507,20 +530,28 @@ client.nullableOptional().createComplexProfile( .id("id") .username("username") .createdAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) - .email("email") + .email( + OptionalNullable.of("email") + ) .phone("phone") - .updatedAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + .updatedAt( + OptionalNullable.of(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + ) .address( Address .builder() .street("street") .zipCode("zipCode") + .city( + OptionalNullable.of("city") + ) + .state("state") .country( OptionalNullable.of("country") ) - .city("city") - .state("state") - .buildingId("buildingId") + .buildingId( + OptionalNullable.of("buildingId") + ) .tenantId("tenantId") .build() ) @@ -528,7 +559,7 @@ client.nullableOptional().createComplexProfile( ) ) .nullableArray( - Optional.of( + OptionalNullable.of( Arrays.asList("nullableArray", "nullableArray") ) ) @@ -537,31 +568,45 @@ client.nullableOptional().createComplexProfile( Arrays.asList("optionalArray", "optionalArray") ) ) + .optionalNullableArray( + OptionalNullable.of( + Arrays.asList("optionalNullableArray", "optionalNullableArray") + ) + ) .nullableListOfNullables( - Optional.of( - Arrays.asList(Optional.of("nullableListOfNullables"), Optional.of("nullableListOfNullables")) + OptionalNullable.of( + Arrays.asList( + OptionalNullable.of("nullableListOfNullables"), + OptionalNullable.of("nullableListOfNullables") + ) ) ) .nullableMapOfNullables( - new HashMap>() {{ - put("nullableMapOfNullables", Optional.of( - Address - .builder() - .street("street") - .zipCode("zipCode") - .country( - OptionalNullable.of("country") - ) - .city(Optional.of("city")) - .state(Optional.of("state")) - .buildingId(Optional.of("buildingId")) - .tenantId(Optional.of("tenantId")) - .build() - )); - }} + OptionalNullable.of( + new HashMap>() {{ + put("nullableMapOfNullables", OptionalNullable.of( + Address + .builder() + .street("street") + .zipCode("zipCode") + .city( + OptionalNullable.of("city") + ) + .state(Optional.of("state")) + .country( + OptionalNullable.of("country") + ) + .buildingId( + OptionalNullable.of("buildingId") + ) + .tenantId(Optional.of("tenantId")) + .build() + )); + }} + ) ) .nullableListOfUnions( - Optional.of( + OptionalNullable.of( Arrays.asList( NotificationMethod.email( EmailNotification @@ -726,20 +771,28 @@ client.nullableOptional().updateComplexProfile( .id("id") .username("username") .createdAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) - .email("email") + .email( + OptionalNullable.of("email") + ) .phone("phone") - .updatedAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + .updatedAt( + OptionalNullable.of(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + ) .address( Address .builder() .street("street") .zipCode("zipCode") + .city( + OptionalNullable.of("city") + ) + .state("state") .country( OptionalNullable.of("country") ) - .city("city") - .state("state") - .buildingId("buildingId") + .buildingId( + OptionalNullable.of("buildingId") + ) .tenantId("tenantId") .build() ) @@ -851,21 +904,27 @@ client.nullableOptional().testDeserialization( DeserializationTestRequest .builder() .requiredString("requiredString") + .nullableString( + OptionalNullable.of("nullableString") + ) + .optionalString("optionalString") .optionalNullableString( OptionalNullable.of("optionalNullableString") ) - .nullableString("nullableString") - .optionalString("optionalString") - .nullableEnum(UserRole.ADMIN) + .nullableEnum( + OptionalNullable.of(UserRole.ADMIN) + ) .optionalEnum(UserStatus.ACTIVE) .nullableUnion( - NotificationMethod.email( - EmailNotification - .builder() - .emailAddress("emailAddress") - .subject("subject") - .htmlContent("htmlContent") - .build() + OptionalNullable.of( + NotificationMethod.email( + EmailNotification + .builder() + .emailAddress("emailAddress") + .subject("subject") + .htmlContent("htmlContent") + .build() + ) ) ) .optionalUnion( @@ -875,20 +934,28 @@ client.nullableOptional().testDeserialization( .id("id") .username("username") .createdAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) - .email("email") + .email( + OptionalNullable.of("email") + ) .phone("phone") - .updatedAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + .updatedAt( + OptionalNullable.of(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + ) .address( Address .builder() .street("street") .zipCode("zipCode") + .city( + OptionalNullable.of("city") + ) + .state("state") .country( OptionalNullable.of("country") ) - .city("city") - .state("state") - .buildingId("buildingId") + .buildingId( + OptionalNullable.of("buildingId") + ) .tenantId("tenantId") .build() ) @@ -896,35 +963,45 @@ client.nullableOptional().testDeserialization( ) ) .nullableList( - Optional.of( + OptionalNullable.of( Arrays.asList("nullableList", "nullableList") ) ) .nullableMap( - new HashMap() {{ - put("nullableMap", 1); - }} + OptionalNullable.of( + new HashMap() {{ + put("nullableMap", 1); + }} + ) ) .nullableObject( - Address - .builder() - .street("street") - .zipCode("zipCode") - .country( - OptionalNullable.of("country") - ) - .city("city") - .state("state") - .buildingId("buildingId") - .tenantId("tenantId") - .build() + OptionalNullable.of( + Address + .builder() + .street("street") + .zipCode("zipCode") + .city( + OptionalNullable.of("city") + ) + .state("state") + .country( + OptionalNullable.of("country") + ) + .buildingId( + OptionalNullable.of("buildingId") + ) + .tenantId("tenantId") + .build() + ) ) .optionalObject( Organization .builder() .id("id") .name("name") - .domain("domain") + .domain( + OptionalNullable.of("domain") + ) .employeeCount(1) .build() ) @@ -986,10 +1063,12 @@ Filter users by role with nullable enum client.nullableOptional().filterByRole( FilterByRoleRequest .builder() + .role( + OptionalNullable.of(UserRole.ADMIN) + ) .secondaryRole( OptionalNullable.of(UserRole.ADMIN) ) - .role(UserRole.ADMIN) .status(UserStatus.ACTIVE) .build() ); @@ -1120,14 +1199,14 @@ client.nullableOptional().updateTags( "userId", UpdateTagsRequest .builder() - .labels( + .tags( OptionalNullable.of( - Arrays.asList("labels", "labels") + Arrays.asList("tags", "tags") ) ) - .tags( - Optional.of( - Arrays.asList("tags", "tags") + .labels( + OptionalNullable.of( + Arrays.asList("labels", "labels") ) ) .categories( @@ -1219,13 +1298,13 @@ client.nullableOptional().getSearchResults( .builder() .query("query") .includeTypes( - Optional.of( + OptionalNullable.of( Arrays.asList("includeTypes", "includeTypes") ) ) .filters( - new HashMap>() {{ - put("filters", Optional.of("filters")); + new HashMap>() {{ + put("filters", OptionalNullable.of("filters")); }} ) .build() diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/snippet.json b/seed/java-sdk/nullable-optional/collapse-optional-nullable/snippet.json index f99cdb4ed4fa..54c82f2c1069 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/snippet.json +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/snippet.json @@ -22,8 +22,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.CreateUserRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createUser(\n CreateUserRequest\n .builder()\n .username(\"username\")\n .address(\n OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n )\n .email(\"email\")\n .phone(\"phone\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.CreateUserRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createUser(\n CreateUserRequest\n .builder()\n .username(\"username\")\n .address(\n OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n )\n .email(\"email\")\n .phone(\"phone\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.CreateUserRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createUser(\n CreateUserRequest\n .builder()\n .username(\"username\")\n .email(\n OptionalNullable.of(\"email\")\n )\n .phone(\"phone\")\n .address(\n OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n )\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.CreateUserRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createUser(\n CreateUserRequest\n .builder()\n .username(\"username\")\n .email(\n OptionalNullable.of(\"email\")\n )\n .phone(\"phone\")\n .address(\n OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n )\n .build()\n );\n }\n}\n" } }, { @@ -35,8 +35,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UpdateUserRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateUser(\n \"userId\",\n UpdateUserRequest\n .builder()\n .email(\n OptionalNullable.of(\"email\")\n )\n .address(\n OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n )\n .username(\"username\")\n .phone(\"phone\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UpdateUserRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateUser(\n \"userId\",\n UpdateUserRequest\n .builder()\n .email(\n OptionalNullable.of(\"email\")\n )\n .address(\n OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n )\n .username(\"username\")\n .phone(\"phone\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UpdateUserRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateUser(\n \"userId\",\n UpdateUserRequest\n .builder()\n .email(\n OptionalNullable.of(\"email\")\n )\n .address(\n OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n )\n .username(\"username\")\n .phone(\"phone\")\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UpdateUserRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateUser(\n \"userId\",\n UpdateUserRequest\n .builder()\n .email(\n OptionalNullable.of(\"email\")\n )\n .address(\n OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n )\n .username(\"username\")\n .phone(\"phone\")\n .build()\n );\n }\n}\n" } }, { @@ -61,8 +61,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchUsersRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().searchUsers(\n SearchUsersRequest\n .builder()\n .query(\"query\")\n .isActive(\n OptionalNullable.of(true)\n )\n .department(\"department\")\n .role(\"role\")\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchUsersRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().searchUsers(\n SearchUsersRequest\n .builder()\n .query(\"query\")\n .isActive(\n OptionalNullable.of(true)\n )\n .department(\"department\")\n .role(\"role\")\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchUsersRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().searchUsers(\n SearchUsersRequest\n .builder()\n .query(\"query\")\n .department(\n OptionalNullable.of(\"department\")\n )\n .isActive(\n OptionalNullable.of(true)\n )\n .role(\"role\")\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchUsersRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().searchUsers(\n SearchUsersRequest\n .builder()\n .query(\"query\")\n .department(\n OptionalNullable.of(\"department\")\n )\n .isActive(\n OptionalNullable.of(true)\n )\n .role(\"role\")\n .build()\n );\n }\n}\n" } }, { @@ -74,8 +74,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.ComplexProfile;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createComplexProfile(\n ComplexProfile\n .builder()\n .id(\"id\")\n .optionalNullableRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .optionalNullableStatus(\n OptionalNullable.of(UserStatus.ACTIVE)\n )\n .optionalNullableNotification(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .optionalNullableArray(\n OptionalNullable.of(\n Arrays.asList(\"optionalNullableArray\", \"optionalNullableArray\")\n )\n )\n .nullableRole(UserRole.ADMIN)\n .optionalRole(UserRole.ADMIN)\n .nullableStatus(UserStatus.ACTIVE)\n .optionalStatus(UserStatus.ACTIVE)\n .nullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .nullableSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .optionalSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n Optional.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .optionalArray(\n Optional.of(\n Arrays.asList(\"optionalArray\", \"optionalArray\")\n )\n )\n .nullableListOfNullables(\n Optional.of(\n Arrays.asList(Optional.of(\"nullableListOfNullables\"), Optional.of(\"nullableListOfNullables\"))\n )\n )\n .nullableMapOfNullables(\n new HashMap>() {{\n put(\"nullableMapOfNullables\", Optional.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(Optional.of(\"city\"))\n .state(Optional.of(\"state\"))\n .buildingId(Optional.of(\"buildingId\"))\n .tenantId(Optional.of(\"tenantId\"))\n .build()\n ));\n }}\n )\n .nullableListOfUnions(\n Optional.of(\n Arrays.asList(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n ),\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n )\n .optionalMapOfEnums(\n new HashMap() {{\n put(\"optionalMapOfEnums\", UserRole.ADMIN);\n }}\n )\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.ComplexProfile;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createComplexProfile(\n ComplexProfile\n .builder()\n .id(\"id\")\n .optionalNullableRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .optionalNullableStatus(\n OptionalNullable.of(UserStatus.ACTIVE)\n )\n .optionalNullableNotification(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .optionalNullableArray(\n OptionalNullable.of(\n Arrays.asList(\"optionalNullableArray\", \"optionalNullableArray\")\n )\n )\n .nullableRole(UserRole.ADMIN)\n .optionalRole(UserRole.ADMIN)\n .nullableStatus(UserStatus.ACTIVE)\n .optionalStatus(UserStatus.ACTIVE)\n .nullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .nullableSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .optionalSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n Optional.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .optionalArray(\n Optional.of(\n Arrays.asList(\"optionalArray\", \"optionalArray\")\n )\n )\n .nullableListOfNullables(\n Optional.of(\n Arrays.asList(Optional.of(\"nullableListOfNullables\"), Optional.of(\"nullableListOfNullables\"))\n )\n )\n .nullableMapOfNullables(\n new HashMap>() {{\n put(\"nullableMapOfNullables\", Optional.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(Optional.of(\"city\"))\n .state(Optional.of(\"state\"))\n .buildingId(Optional.of(\"buildingId\"))\n .tenantId(Optional.of(\"tenantId\"))\n .build()\n ));\n }}\n )\n .nullableListOfUnions(\n Optional.of(\n Arrays.asList(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n ),\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n )\n .optionalMapOfEnums(\n new HashMap() {{\n put(\"optionalMapOfEnums\", UserRole.ADMIN);\n }}\n )\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.ComplexProfile;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createComplexProfile(\n ComplexProfile\n .builder()\n .id(\"id\")\n .nullableRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .optionalRole(UserRole.ADMIN)\n .optionalNullableRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .nullableStatus(\n OptionalNullable.of(UserStatus.ACTIVE)\n )\n .optionalStatus(UserStatus.ACTIVE)\n .optionalNullableStatus(\n OptionalNullable.of(UserStatus.ACTIVE)\n )\n .nullableNotification(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .optionalNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNullableNotification(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .nullableSearchResult(\n OptionalNullable.of(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\n OptionalNullable.of(\"email\")\n )\n .phone(\"phone\")\n .updatedAt(\n OptionalNullable.of(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n )\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n )\n .optionalSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\n OptionalNullable.of(\"email\")\n )\n .phone(\"phone\")\n .updatedAt(\n OptionalNullable.of(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n )\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n OptionalNullable.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .optionalArray(\n Optional.of(\n Arrays.asList(\"optionalArray\", \"optionalArray\")\n )\n )\n .optionalNullableArray(\n OptionalNullable.of(\n Arrays.asList(\"optionalNullableArray\", \"optionalNullableArray\")\n )\n )\n .nullableListOfNullables(\n OptionalNullable.of(\n Arrays.asList(\n OptionalNullable.of(\"nullableListOfNullables\"),\n OptionalNullable.of(\"nullableListOfNullables\")\n )\n )\n )\n .nullableMapOfNullables(\n OptionalNullable.of(\n new HashMap>() {{\n put(\"nullableMapOfNullables\", OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(Optional.of(\"state\"))\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(Optional.of(\"tenantId\"))\n .build()\n ));\n }}\n )\n )\n .nullableListOfUnions(\n OptionalNullable.of(\n Arrays.asList(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n ),\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n )\n .optionalMapOfEnums(\n new HashMap() {{\n put(\"optionalMapOfEnums\", UserRole.ADMIN);\n }}\n )\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.ComplexProfile;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createComplexProfile(\n ComplexProfile\n .builder()\n .id(\"id\")\n .nullableRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .optionalRole(UserRole.ADMIN)\n .optionalNullableRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .nullableStatus(\n OptionalNullable.of(UserStatus.ACTIVE)\n )\n .optionalStatus(UserStatus.ACTIVE)\n .optionalNullableStatus(\n OptionalNullable.of(UserStatus.ACTIVE)\n )\n .nullableNotification(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .optionalNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNullableNotification(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .nullableSearchResult(\n OptionalNullable.of(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\n OptionalNullable.of(\"email\")\n )\n .phone(\"phone\")\n .updatedAt(\n OptionalNullable.of(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n )\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n )\n .optionalSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\n OptionalNullable.of(\"email\")\n )\n .phone(\"phone\")\n .updatedAt(\n OptionalNullable.of(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n )\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n OptionalNullable.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .optionalArray(\n Optional.of(\n Arrays.asList(\"optionalArray\", \"optionalArray\")\n )\n )\n .optionalNullableArray(\n OptionalNullable.of(\n Arrays.asList(\"optionalNullableArray\", \"optionalNullableArray\")\n )\n )\n .nullableListOfNullables(\n OptionalNullable.of(\n Arrays.asList(\n OptionalNullable.of(\"nullableListOfNullables\"),\n OptionalNullable.of(\"nullableListOfNullables\")\n )\n )\n )\n .nullableMapOfNullables(\n OptionalNullable.of(\n new HashMap>() {{\n put(\"nullableMapOfNullables\", OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(Optional.of(\"state\"))\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(Optional.of(\"tenantId\"))\n .build()\n ));\n }}\n )\n )\n .nullableListOfUnions(\n OptionalNullable.of(\n Arrays.asList(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n ),\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n )\n .optionalMapOfEnums(\n new HashMap() {{\n put(\"optionalMapOfEnums\", UserRole.ADMIN);\n }}\n )\n .build()\n );\n }\n}\n" } }, { @@ -100,8 +100,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateComplexProfileRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateComplexProfile(\n \"profileId\",\n UpdateComplexProfileRequest\n .builder()\n .nullableRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .nullableStatus(\n OptionalNullable.of(UserStatus.ACTIVE)\n )\n .nullableNotification(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .nullableSearchResult(\n OptionalNullable.of(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n )\n .nullableArray(\n OptionalNullable.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateComplexProfileRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateComplexProfile(\n \"profileId\",\n UpdateComplexProfileRequest\n .builder()\n .nullableRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .nullableStatus(\n OptionalNullable.of(UserStatus.ACTIVE)\n )\n .nullableNotification(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .nullableSearchResult(\n OptionalNullable.of(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n )\n .nullableArray(\n OptionalNullable.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateComplexProfileRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateComplexProfile(\n \"profileId\",\n UpdateComplexProfileRequest\n .builder()\n .nullableRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .nullableStatus(\n OptionalNullable.of(UserStatus.ACTIVE)\n )\n .nullableNotification(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .nullableSearchResult(\n OptionalNullable.of(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\n OptionalNullable.of(\"email\")\n )\n .phone(\"phone\")\n .updatedAt(\n OptionalNullable.of(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n )\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n )\n .nullableArray(\n OptionalNullable.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateComplexProfileRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateComplexProfile(\n \"profileId\",\n UpdateComplexProfileRequest\n .builder()\n .nullableRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .nullableStatus(\n OptionalNullable.of(UserStatus.ACTIVE)\n )\n .nullableNotification(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .nullableSearchResult(\n OptionalNullable.of(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\n OptionalNullable.of(\"email\")\n )\n .phone(\"phone\")\n .updatedAt(\n OptionalNullable.of(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n )\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n )\n .nullableArray(\n OptionalNullable.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .build()\n );\n }\n}\n" } }, { @@ -113,8 +113,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.DeserializationTestRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Organization;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().testDeserialization(\n DeserializationTestRequest\n .builder()\n .requiredString(\"requiredString\")\n .optionalNullableString(\n OptionalNullable.of(\"optionalNullableString\")\n )\n .nullableString(\"nullableString\")\n .optionalString(\"optionalString\")\n .nullableEnum(UserRole.ADMIN)\n .optionalEnum(UserStatus.ACTIVE)\n .nullableUnion(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalUnion(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableList(\n Optional.of(\n Arrays.asList(\"nullableList\", \"nullableList\")\n )\n )\n .nullableMap(\n new HashMap() {{\n put(\"nullableMap\", 1);\n }}\n )\n .nullableObject(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .optionalObject(\n Organization\n .builder()\n .id(\"id\")\n .name(\"name\")\n .domain(\"domain\")\n .employeeCount(1)\n .build()\n )\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.DeserializationTestRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Organization;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().testDeserialization(\n DeserializationTestRequest\n .builder()\n .requiredString(\"requiredString\")\n .optionalNullableString(\n OptionalNullable.of(\"optionalNullableString\")\n )\n .nullableString(\"nullableString\")\n .optionalString(\"optionalString\")\n .nullableEnum(UserRole.ADMIN)\n .optionalEnum(UserStatus.ACTIVE)\n .nullableUnion(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalUnion(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableList(\n Optional.of(\n Arrays.asList(\"nullableList\", \"nullableList\")\n )\n )\n .nullableMap(\n new HashMap() {{\n put(\"nullableMap\", 1);\n }}\n )\n .nullableObject(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .city(\"city\")\n .state(\"state\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .optionalObject(\n Organization\n .builder()\n .id(\"id\")\n .name(\"name\")\n .domain(\"domain\")\n .employeeCount(1)\n .build()\n )\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.DeserializationTestRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Organization;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().testDeserialization(\n DeserializationTestRequest\n .builder()\n .requiredString(\"requiredString\")\n .nullableString(\n OptionalNullable.of(\"nullableString\")\n )\n .optionalString(\"optionalString\")\n .optionalNullableString(\n OptionalNullable.of(\"optionalNullableString\")\n )\n .nullableEnum(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .optionalEnum(UserStatus.ACTIVE)\n .nullableUnion(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .optionalUnion(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\n OptionalNullable.of(\"email\")\n )\n .phone(\"phone\")\n .updatedAt(\n OptionalNullable.of(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n )\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableList(\n OptionalNullable.of(\n Arrays.asList(\"nullableList\", \"nullableList\")\n )\n )\n .nullableMap(\n OptionalNullable.of(\n new HashMap() {{\n put(\"nullableMap\", 1);\n }}\n )\n )\n .nullableObject(\n OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n )\n .optionalObject(\n Organization\n .builder()\n .id(\"id\")\n .name(\"name\")\n .domain(\n OptionalNullable.of(\"domain\")\n )\n .employeeCount(1)\n .build()\n )\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.DeserializationTestRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Organization;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().testDeserialization(\n DeserializationTestRequest\n .builder()\n .requiredString(\"requiredString\")\n .nullableString(\n OptionalNullable.of(\"nullableString\")\n )\n .optionalString(\"optionalString\")\n .optionalNullableString(\n OptionalNullable.of(\"optionalNullableString\")\n )\n .nullableEnum(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .optionalEnum(UserStatus.ACTIVE)\n .nullableUnion(\n OptionalNullable.of(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .optionalUnion(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\n OptionalNullable.of(\"email\")\n )\n .phone(\"phone\")\n .updatedAt(\n OptionalNullable.of(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n )\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableList(\n OptionalNullable.of(\n Arrays.asList(\"nullableList\", \"nullableList\")\n )\n )\n .nullableMap(\n OptionalNullable.of(\n new HashMap() {{\n put(\"nullableMap\", 1);\n }}\n )\n )\n .nullableObject(\n OptionalNullable.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\n OptionalNullable.of(\"city\")\n )\n .state(\"state\")\n .country(\n OptionalNullable.of(\"country\")\n )\n .buildingId(\n OptionalNullable.of(\"buildingId\")\n )\n .tenantId(\"tenantId\")\n .build()\n )\n )\n .optionalObject(\n Organization\n .builder()\n .id(\"id\")\n .name(\"name\")\n .domain(\n OptionalNullable.of(\"domain\")\n )\n .employeeCount(1)\n .build()\n )\n .build()\n );\n }\n}\n" } }, { @@ -126,8 +126,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.FilterByRoleRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().filterByRole(\n FilterByRoleRequest\n .builder()\n .secondaryRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .role(UserRole.ADMIN)\n .status(UserStatus.ACTIVE)\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.FilterByRoleRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().filterByRole(\n FilterByRoleRequest\n .builder()\n .secondaryRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .role(UserRole.ADMIN)\n .status(UserStatus.ACTIVE)\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.FilterByRoleRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().filterByRole(\n FilterByRoleRequest\n .builder()\n .role(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .secondaryRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .status(UserStatus.ACTIVE)\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.FilterByRoleRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().filterByRole(\n FilterByRoleRequest\n .builder()\n .role(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .secondaryRole(\n OptionalNullable.of(UserRole.ADMIN)\n )\n .status(UserStatus.ACTIVE)\n .build()\n );\n }\n}\n" } }, { @@ -152,8 +152,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateTagsRequest;\nimport java.util.Arrays;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateTags(\n \"userId\",\n UpdateTagsRequest\n .builder()\n .labels(\n OptionalNullable.of(\n Arrays.asList(\"labels\", \"labels\")\n )\n )\n .tags(\n Optional.of(\n Arrays.asList(\"tags\", \"tags\")\n )\n )\n .categories(\n Optional.of(\n Arrays.asList(\"categories\", \"categories\")\n )\n )\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateTagsRequest;\nimport java.util.Arrays;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateTags(\n \"userId\",\n UpdateTagsRequest\n .builder()\n .labels(\n OptionalNullable.of(\n Arrays.asList(\"labels\", \"labels\")\n )\n )\n .tags(\n Optional.of(\n Arrays.asList(\"tags\", \"tags\")\n )\n )\n .categories(\n Optional.of(\n Arrays.asList(\"categories\", \"categories\")\n )\n )\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateTagsRequest;\nimport java.util.Arrays;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateTags(\n \"userId\",\n UpdateTagsRequest\n .builder()\n .tags(\n OptionalNullable.of(\n Arrays.asList(\"tags\", \"tags\")\n )\n )\n .labels(\n OptionalNullable.of(\n Arrays.asList(\"labels\", \"labels\")\n )\n )\n .categories(\n Optional.of(\n Arrays.asList(\"categories\", \"categories\")\n )\n )\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateTagsRequest;\nimport java.util.Arrays;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateTags(\n \"userId\",\n UpdateTagsRequest\n .builder()\n .tags(\n OptionalNullable.of(\n Arrays.asList(\"tags\", \"tags\")\n )\n )\n .labels(\n OptionalNullable.of(\n Arrays.asList(\"labels\", \"labels\")\n )\n )\n .categories(\n Optional.of(\n Arrays.asList(\"categories\", \"categories\")\n )\n )\n .build()\n );\n }\n}\n" } }, { @@ -165,8 +165,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchRequest;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().getSearchResults(\n SearchRequest\n .builder()\n .query(\"query\")\n .includeTypes(\n Optional.of(\n Arrays.asList(\"includeTypes\", \"includeTypes\")\n )\n )\n .filters(\n new HashMap>() {{\n put(\"filters\", Optional.of(\"filters\"));\n }}\n )\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchRequest;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().getSearchResults(\n SearchRequest\n .builder()\n .query(\"query\")\n .includeTypes(\n Optional.of(\n Arrays.asList(\"includeTypes\", \"includeTypes\")\n )\n )\n .filters(\n new HashMap>() {{\n put(\"filters\", Optional.of(\"filters\"));\n }}\n )\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchRequest;\nimport java.util.Arrays;\nimport java.util.HashMap;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().getSearchResults(\n SearchRequest\n .builder()\n .query(\"query\")\n .includeTypes(\n OptionalNullable.of(\n Arrays.asList(\"includeTypes\", \"includeTypes\")\n )\n )\n .filters(\n new HashMap>() {{\n put(\"filters\", OptionalNullable.of(\"filters\"));\n }}\n )\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.core.OptionalNullable;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchRequest;\nimport java.util.Arrays;\nimport java.util.HashMap;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().getSearchResults(\n SearchRequest\n .builder()\n .query(\"query\")\n .includeTypes(\n OptionalNullable.of(\n Arrays.asList(\"includeTypes\", \"includeTypes\")\n )\n )\n .filters(\n new HashMap>() {{\n put(\"filters\", OptionalNullable.of(\"filters\"));\n }}\n )\n .build()\n );\n }\n}\n" } } ], diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example1.java b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example1.java index 3c6ba69e86bf..a3c6a779b410 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example1.java +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example1.java @@ -13,17 +13,17 @@ public static void main(String[] args) { client.nullableOptional() .createUser(CreateUserRequest.builder() .username("username") + .email(OptionalNullable.of("email")) + .phone("phone") .address(OptionalNullable.of(Address.builder() .street("street") .zipCode("zipCode") - .country(OptionalNullable.of("country")) - .city("city") + .city(OptionalNullable.of("city")) .state("state") - .buildingId("buildingId") + .country(OptionalNullable.of("country")) + .buildingId(OptionalNullable.of("buildingId")) .tenantId("tenantId") .build())) - .email("email") - .phone("phone") .build()); } } diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example11.java b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example11.java index 09ef9e5ff78c..f0ecbd52ccf1 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example11.java +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example11.java @@ -15,8 +15,8 @@ public static void main(String[] args) { .updateTags( "userId", UpdateTagsRequest.builder() + .tags(OptionalNullable.of(Arrays.asList("tags", "tags"))) .labels(OptionalNullable.of(Arrays.asList("labels", "labels"))) - .tags(Optional.of(Arrays.asList("tags", "tags"))) .categories(Optional.of(Arrays.asList("categories", "categories"))) .build()); } diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example12.java b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example12.java index 524dfdff3f98..91bf1fd48cb7 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example12.java +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example12.java @@ -1,10 +1,10 @@ package com.snippets; import com.seed.nullableOptional.SeedNullableOptionalClient; +import com.seed.nullableOptional.core.OptionalNullable; import com.seed.nullableOptional.resources.nullableoptional.requests.SearchRequest; import java.util.Arrays; import java.util.HashMap; -import java.util.Optional; public class Example12 { public static void main(String[] args) { @@ -14,10 +14,10 @@ public static void main(String[] args) { client.nullableOptional() .getSearchResults(SearchRequest.builder() .query("query") - .includeTypes(Optional.of(Arrays.asList("includeTypes", "includeTypes"))) - .filters(new HashMap>() { + .includeTypes(OptionalNullable.of(Arrays.asList("includeTypes", "includeTypes"))) + .filters(new HashMap>() { { - put("filters", Optional.of("filters")); + put("filters", OptionalNullable.of("filters")); } }) .build()); diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example2.java b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example2.java index ff94785d4f4a..2913bb9781c1 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example2.java +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example2.java @@ -18,10 +18,10 @@ public static void main(String[] args) { .address(OptionalNullable.of(Address.builder() .street("street") .zipCode("zipCode") - .country(OptionalNullable.of("country")) - .city("city") + .city(OptionalNullable.of("city")) .state("state") - .buildingId("buildingId") + .country(OptionalNullable.of("country")) + .buildingId(OptionalNullable.of("buildingId")) .tenantId("tenantId") .build())) .username("username") diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example4.java b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example4.java index 4ab4cf544f16..eb1204cc41e2 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example4.java +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example4.java @@ -12,8 +12,8 @@ public static void main(String[] args) { client.nullableOptional() .searchUsers(SearchUsersRequest.builder() .query("query") + .department(OptionalNullable.of("department")) .isActive(OptionalNullable.of(true)) - .department("department") .role("role") .build()); } diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example5.java b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example5.java index 433784fe3f2c..1901add5df62 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example5.java +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example5.java @@ -23,84 +23,85 @@ public static void main(String[] args) { client.nullableOptional() .createComplexProfile(ComplexProfile.builder() .id("id") - .optionalNullableRole(OptionalNullable.of(UserRole.ADMIN)) - .optionalNullableStatus(OptionalNullable.of(UserStatus.ACTIVE)) - .optionalNullableNotification( - OptionalNullable.of(NotificationMethod.email(EmailNotification.builder() - .emailAddress("emailAddress") - .subject("subject") - .htmlContent("htmlContent") - .build()))) - .optionalNullableArray( - OptionalNullable.of(Arrays.asList("optionalNullableArray", "optionalNullableArray"))) - .nullableRole(UserRole.ADMIN) + .nullableRole(OptionalNullable.of(UserRole.ADMIN)) .optionalRole(UserRole.ADMIN) - .nullableStatus(UserStatus.ACTIVE) + .optionalNullableRole(OptionalNullable.of(UserRole.ADMIN)) + .nullableStatus(OptionalNullable.of(UserStatus.ACTIVE)) .optionalStatus(UserStatus.ACTIVE) - .nullableNotification(NotificationMethod.email(EmailNotification.builder() + .optionalNullableStatus(OptionalNullable.of(UserStatus.ACTIVE)) + .nullableNotification(OptionalNullable.of(NotificationMethod.email(EmailNotification.builder() .emailAddress("emailAddress") .subject("subject") .htmlContent("htmlContent") - .build())) + .build()))) .optionalNotification(NotificationMethod.email(EmailNotification.builder() .emailAddress("emailAddress") .subject("subject") .htmlContent("htmlContent") .build())) - .nullableSearchResult(SearchResult.user(UserResponse.builder() + .optionalNullableNotification( + OptionalNullable.of(NotificationMethod.email(EmailNotification.builder() + .emailAddress("emailAddress") + .subject("subject") + .htmlContent("htmlContent") + .build()))) + .nullableSearchResult(OptionalNullable.of(SearchResult.user(UserResponse.builder() .id("id") .username("username") .createdAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) - .email("email") + .email(OptionalNullable.of("email")) .phone("phone") - .updatedAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + .updatedAt(OptionalNullable.of(OffsetDateTime.parse("2024-01-15T09:30:00Z"))) .address(Address.builder() .street("street") .zipCode("zipCode") - .country(OptionalNullable.of("country")) - .city("city") + .city(OptionalNullable.of("city")) .state("state") - .buildingId("buildingId") + .country(OptionalNullable.of("country")) + .buildingId(OptionalNullable.of("buildingId")) .tenantId("tenantId") .build()) - .build())) + .build()))) .optionalSearchResult(SearchResult.user(UserResponse.builder() .id("id") .username("username") .createdAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) - .email("email") + .email(OptionalNullable.of("email")) .phone("phone") - .updatedAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + .updatedAt(OptionalNullable.of(OffsetDateTime.parse("2024-01-15T09:30:00Z"))) .address(Address.builder() .street("street") .zipCode("zipCode") - .country(OptionalNullable.of("country")) - .city("city") + .city(OptionalNullable.of("city")) .state("state") - .buildingId("buildingId") + .country(OptionalNullable.of("country")) + .buildingId(OptionalNullable.of("buildingId")) .tenantId("tenantId") .build()) .build())) - .nullableArray(Optional.of(Arrays.asList("nullableArray", "nullableArray"))) + .nullableArray(OptionalNullable.of(Arrays.asList("nullableArray", "nullableArray"))) .optionalArray(Optional.of(Arrays.asList("optionalArray", "optionalArray"))) - .nullableListOfNullables(Optional.of(Arrays.asList( - Optional.of("nullableListOfNullables"), Optional.of("nullableListOfNullables")))) - .nullableMapOfNullables(new HashMap>() { + .optionalNullableArray( + OptionalNullable.of(Arrays.asList("optionalNullableArray", "optionalNullableArray"))) + .nullableListOfNullables(OptionalNullable.of(Arrays.asList( + OptionalNullable.of("nullableListOfNullables"), + OptionalNullable.of("nullableListOfNullables")))) + .nullableMapOfNullables(OptionalNullable.of(new HashMap>() { { put( "nullableMapOfNullables", - Optional.of(Address.builder() + OptionalNullable.of(Address.builder() .street("street") .zipCode("zipCode") - .country(OptionalNullable.of("country")) - .city(Optional.of("city")) + .city(OptionalNullable.of("city")) .state(Optional.of("state")) - .buildingId(Optional.of("buildingId")) + .country(OptionalNullable.of("country")) + .buildingId(OptionalNullable.of("buildingId")) .tenantId(Optional.of("tenantId")) .build())); } - }) - .nullableListOfUnions(Optional.of(Arrays.asList( + })) + .nullableListOfUnions(OptionalNullable.of(Arrays.asList( NotificationMethod.email(EmailNotification.builder() .emailAddress("emailAddress") .subject("subject") diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example7.java b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example7.java index ba4fe9506c30..f734191f03ed 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example7.java +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example7.java @@ -34,16 +34,16 @@ public static void main(String[] args) { .id("id") .username("username") .createdAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) - .email("email") + .email(OptionalNullable.of("email")) .phone("phone") - .updatedAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + .updatedAt(OptionalNullable.of(OffsetDateTime.parse("2024-01-15T09:30:00Z"))) .address(Address.builder() .street("street") .zipCode("zipCode") - .country(OptionalNullable.of("country")) - .city("city") + .city(OptionalNullable.of("city")) .state("state") - .buildingId("buildingId") + .country(OptionalNullable.of("country")) + .buildingId(OptionalNullable.of("buildingId")) .tenantId("tenantId") .build()) .build()))) diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example8.java b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example8.java index 052db7774479..f6f994e7ad5d 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example8.java +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example8.java @@ -14,7 +14,6 @@ import java.time.OffsetDateTime; import java.util.Arrays; import java.util.HashMap; -import java.util.Optional; public class Example8 { public static void main(String[] args) { @@ -24,52 +23,52 @@ public static void main(String[] args) { client.nullableOptional() .testDeserialization(DeserializationTestRequest.builder() .requiredString("requiredString") - .optionalNullableString(OptionalNullable.of("optionalNullableString")) - .nullableString("nullableString") + .nullableString(OptionalNullable.of("nullableString")) .optionalString("optionalString") - .nullableEnum(UserRole.ADMIN) + .optionalNullableString(OptionalNullable.of("optionalNullableString")) + .nullableEnum(OptionalNullable.of(UserRole.ADMIN)) .optionalEnum(UserStatus.ACTIVE) - .nullableUnion(NotificationMethod.email(EmailNotification.builder() + .nullableUnion(OptionalNullable.of(NotificationMethod.email(EmailNotification.builder() .emailAddress("emailAddress") .subject("subject") .htmlContent("htmlContent") - .build())) + .build()))) .optionalUnion(SearchResult.user(UserResponse.builder() .id("id") .username("username") .createdAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) - .email("email") + .email(OptionalNullable.of("email")) .phone("phone") - .updatedAt(OffsetDateTime.parse("2024-01-15T09:30:00Z")) + .updatedAt(OptionalNullable.of(OffsetDateTime.parse("2024-01-15T09:30:00Z"))) .address(Address.builder() .street("street") .zipCode("zipCode") - .country(OptionalNullable.of("country")) - .city("city") + .city(OptionalNullable.of("city")) .state("state") - .buildingId("buildingId") + .country(OptionalNullable.of("country")) + .buildingId(OptionalNullable.of("buildingId")) .tenantId("tenantId") .build()) .build())) - .nullableList(Optional.of(Arrays.asList("nullableList", "nullableList"))) - .nullableMap(new HashMap() { + .nullableList(OptionalNullable.of(Arrays.asList("nullableList", "nullableList"))) + .nullableMap(OptionalNullable.of(new HashMap() { { put("nullableMap", 1); } - }) - .nullableObject(Address.builder() + })) + .nullableObject(OptionalNullable.of(Address.builder() .street("street") .zipCode("zipCode") - .country(OptionalNullable.of("country")) - .city("city") + .city(OptionalNullable.of("city")) .state("state") - .buildingId("buildingId") + .country(OptionalNullable.of("country")) + .buildingId(OptionalNullable.of("buildingId")) .tenantId("tenantId") - .build()) + .build())) .optionalObject(Organization.builder() .id("id") .name("name") - .domain("domain") + .domain(OptionalNullable.of("domain")) .employeeCount(1) .build()) .build()); diff --git a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example9.java b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example9.java index 13b6a15116c3..ed4ec8b6c082 100644 --- a/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example9.java +++ b/seed/java-sdk/nullable-optional/collapse-optional-nullable/src/main/java/com/snippets/Example9.java @@ -13,8 +13,8 @@ public static void main(String[] args) { client.nullableOptional() .filterByRole(FilterByRoleRequest.builder() + .role(OptionalNullable.of(UserRole.ADMIN)) .secondaryRole(OptionalNullable.of(UserRole.ADMIN)) - .role(UserRole.ADMIN) .status(UserStatus.ACTIVE) .build()); } diff --git a/seed/java-sdk/nullable-optional/with-nullable-annotation/reference.md b/seed/java-sdk/nullable-optional/with-nullable-annotation/reference.md index b51d8fa069cf..68b3a8c9742b 100644 --- a/seed/java-sdk/nullable-optional/with-nullable-annotation/reference.md +++ b/seed/java-sdk/nullable-optional/with-nullable-annotation/reference.md @@ -499,9 +499,7 @@ client.nullableOptional().createComplexProfile( ) ) .nullableArray( - Optional.of( - Arrays.asList("nullableArray", "nullableArray") - ) + Arrays.asList("nullableArray", "nullableArray") ) .optionalArray( Optional.of( @@ -509,50 +507,42 @@ client.nullableOptional().createComplexProfile( ) ) .optionalNullableArray( - Optional.of( - Arrays.asList("optionalNullableArray", "optionalNullableArray") - ) + Arrays.asList("optionalNullableArray", "optionalNullableArray") ) .nullableListOfNullables( - Optional.of( - Arrays.asList(Optional.of("nullableListOfNullables"), Optional.of("nullableListOfNullables")) - ) + Arrays.asList("nullableListOfNullables", "nullableListOfNullables") ) .nullableMapOfNullables( - new HashMap>() {{ - put("nullableMapOfNullables", Optional.of( - Address - .builder() - .street("street") - .zipCode("zipCode") - .city(Optional.of("city")) - .state(Optional.of("state")) - .country(Optional.of("country")) - .buildingId(Optional.of("buildingId")) - .tenantId(Optional.of("tenantId")) - .build() - )); + new HashMap() {{ + put("nullableMapOfNullables", Address + .builder() + .street("street") + .zipCode("zipCode") + .city("city") + .state(Optional.of("state")) + .country(Optional.of("country")) + .buildingId("buildingId") + .tenantId(Optional.of("tenantId")) + .build()); }} ) .nullableListOfUnions( - Optional.of( - Arrays.asList( - NotificationMethod.email( - EmailNotification - .builder() - .emailAddress("emailAddress") - .subject("subject") - .htmlContent("htmlContent") - .build() - ), - NotificationMethod.email( - EmailNotification - .builder() - .emailAddress("emailAddress") - .subject("subject") - .htmlContent("htmlContent") - .build() - ) + Arrays.asList( + NotificationMethod.email( + EmailNotification + .builder() + .emailAddress("emailAddress") + .subject("subject") + .htmlContent("htmlContent") + .build() + ), + NotificationMethod.email( + EmailNotification + .builder() + .emailAddress("emailAddress") + .subject("subject") + .htmlContent("htmlContent") + .build() ) ) ) @@ -712,9 +702,7 @@ client.nullableOptional().updateComplexProfile( ) ) .nullableArray( - Optional.of( - Arrays.asList("nullableArray", "nullableArray") - ) + Arrays.asList("nullableArray", "nullableArray") ) .build() ); @@ -856,9 +844,7 @@ client.nullableOptional().testDeserialization( ) ) .nullableList( - Optional.of( - Arrays.asList("nullableList", "nullableList") - ) + Arrays.asList("nullableList", "nullableList") ) .nullableMap( new HashMap() {{ @@ -1077,9 +1063,7 @@ client.nullableOptional().updateTags( UpdateTagsRequest .builder() .tags( - Optional.of( - Arrays.asList("tags", "tags") - ) + Arrays.asList("tags", "tags") ) .categories( Optional.of( @@ -1087,9 +1071,7 @@ client.nullableOptional().updateTags( ) ) .labels( - Optional.of( - Arrays.asList("labels", "labels") - ) + Arrays.asList("labels", "labels") ) .build() ); @@ -1175,13 +1157,11 @@ client.nullableOptional().getSearchResults( .builder() .query("query") .includeTypes( - Optional.of( - Arrays.asList("includeTypes", "includeTypes") - ) + Arrays.asList("includeTypes", "includeTypes") ) .filters( - new HashMap>() {{ - put("filters", Optional.of("filters")); + new HashMap() {{ + put("filters", "filters"); }} ) .build() diff --git a/seed/java-sdk/nullable-optional/with-nullable-annotation/snippet.json b/seed/java-sdk/nullable-optional/with-nullable-annotation/snippet.json index ea0c90e02a75..858d2a744731 100644 --- a/seed/java-sdk/nullable-optional/with-nullable-annotation/snippet.json +++ b/seed/java-sdk/nullable-optional/with-nullable-annotation/snippet.json @@ -74,8 +74,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.ComplexProfile;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createComplexProfile(\n ComplexProfile\n .builder()\n .id(\"id\")\n .nullableRole(UserRole.ADMIN)\n .optionalRole(UserRole.ADMIN)\n .optionalNullableRole(UserRole.ADMIN)\n .nullableStatus(UserStatus.ACTIVE)\n .optionalStatus(UserStatus.ACTIVE)\n .optionalNullableStatus(UserStatus.ACTIVE)\n .nullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .nullableSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .optionalSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n Optional.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .optionalArray(\n Optional.of(\n Arrays.asList(\"optionalArray\", \"optionalArray\")\n )\n )\n .optionalNullableArray(\n Optional.of(\n Arrays.asList(\"optionalNullableArray\", \"optionalNullableArray\")\n )\n )\n .nullableListOfNullables(\n Optional.of(\n Arrays.asList(Optional.of(\"nullableListOfNullables\"), Optional.of(\"nullableListOfNullables\"))\n )\n )\n .nullableMapOfNullables(\n new HashMap>() {{\n put(\"nullableMapOfNullables\", Optional.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(Optional.of(\"city\"))\n .state(Optional.of(\"state\"))\n .country(Optional.of(\"country\"))\n .buildingId(Optional.of(\"buildingId\"))\n .tenantId(Optional.of(\"tenantId\"))\n .build()\n ));\n }}\n )\n .nullableListOfUnions(\n Optional.of(\n Arrays.asList(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n ),\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n )\n .optionalMapOfEnums(\n new HashMap() {{\n put(\"optionalMapOfEnums\", UserRole.ADMIN);\n }}\n )\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.ComplexProfile;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createComplexProfile(\n ComplexProfile\n .builder()\n .id(\"id\")\n .nullableRole(UserRole.ADMIN)\n .optionalRole(UserRole.ADMIN)\n .optionalNullableRole(UserRole.ADMIN)\n .nullableStatus(UserStatus.ACTIVE)\n .optionalStatus(UserStatus.ACTIVE)\n .optionalNullableStatus(UserStatus.ACTIVE)\n .nullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .nullableSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .optionalSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n Optional.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .optionalArray(\n Optional.of(\n Arrays.asList(\"optionalArray\", \"optionalArray\")\n )\n )\n .optionalNullableArray(\n Optional.of(\n Arrays.asList(\"optionalNullableArray\", \"optionalNullableArray\")\n )\n )\n .nullableListOfNullables(\n Optional.of(\n Arrays.asList(Optional.of(\"nullableListOfNullables\"), Optional.of(\"nullableListOfNullables\"))\n )\n )\n .nullableMapOfNullables(\n new HashMap>() {{\n put(\"nullableMapOfNullables\", Optional.of(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(Optional.of(\"city\"))\n .state(Optional.of(\"state\"))\n .country(Optional.of(\"country\"))\n .buildingId(Optional.of(\"buildingId\"))\n .tenantId(Optional.of(\"tenantId\"))\n .build()\n ));\n }}\n )\n .nullableListOfUnions(\n Optional.of(\n Arrays.asList(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n ),\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n )\n .optionalMapOfEnums(\n new HashMap() {{\n put(\"optionalMapOfEnums\", UserRole.ADMIN);\n }}\n )\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.ComplexProfile;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createComplexProfile(\n ComplexProfile\n .builder()\n .id(\"id\")\n .nullableRole(UserRole.ADMIN)\n .optionalRole(UserRole.ADMIN)\n .optionalNullableRole(UserRole.ADMIN)\n .nullableStatus(UserStatus.ACTIVE)\n .optionalStatus(UserStatus.ACTIVE)\n .optionalNullableStatus(UserStatus.ACTIVE)\n .nullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .nullableSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .optionalSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n .optionalArray(\n Optional.of(\n Arrays.asList(\"optionalArray\", \"optionalArray\")\n )\n )\n .optionalNullableArray(\n Arrays.asList(\"optionalNullableArray\", \"optionalNullableArray\")\n )\n .nullableListOfNullables(\n Arrays.asList(\"nullableListOfNullables\", \"nullableListOfNullables\")\n )\n .nullableMapOfNullables(\n new HashMap() {{\n put(\"nullableMapOfNullables\", Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(Optional.of(\"state\"))\n .country(Optional.of(\"country\"))\n .buildingId(\"buildingId\")\n .tenantId(Optional.of(\"tenantId\"))\n .build());\n }}\n )\n .nullableListOfUnions(\n Arrays.asList(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n ),\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .optionalMapOfEnums(\n new HashMap() {{\n put(\"optionalMapOfEnums\", UserRole.ADMIN);\n }}\n )\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.ComplexProfile;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().createComplexProfile(\n ComplexProfile\n .builder()\n .id(\"id\")\n .nullableRole(UserRole.ADMIN)\n .optionalRole(UserRole.ADMIN)\n .optionalNullableRole(UserRole.ADMIN)\n .nullableStatus(UserStatus.ACTIVE)\n .optionalStatus(UserStatus.ACTIVE)\n .optionalNullableStatus(UserStatus.ACTIVE)\n .nullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalNullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .nullableSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .optionalSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n .optionalArray(\n Optional.of(\n Arrays.asList(\"optionalArray\", \"optionalArray\")\n )\n )\n .optionalNullableArray(\n Arrays.asList(\"optionalNullableArray\", \"optionalNullableArray\")\n )\n .nullableListOfNullables(\n Arrays.asList(\"nullableListOfNullables\", \"nullableListOfNullables\")\n )\n .nullableMapOfNullables(\n new HashMap() {{\n put(\"nullableMapOfNullables\", Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(Optional.of(\"state\"))\n .country(Optional.of(\"country\"))\n .buildingId(\"buildingId\")\n .tenantId(Optional.of(\"tenantId\"))\n .build());\n }}\n )\n .nullableListOfUnions(\n Arrays.asList(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n ),\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n )\n .optionalMapOfEnums(\n new HashMap() {{\n put(\"optionalMapOfEnums\", UserRole.ADMIN);\n }}\n )\n .build()\n );\n }\n}\n" } }, { @@ -100,8 +100,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateComplexProfileRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateComplexProfile(\n \"profileId\",\n UpdateComplexProfileRequest\n .builder()\n .nullableRole(UserRole.ADMIN)\n .nullableStatus(UserStatus.ACTIVE)\n .nullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .nullableSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n Optional.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateComplexProfileRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateComplexProfile(\n \"profileId\",\n UpdateComplexProfileRequest\n .builder()\n .nullableRole(UserRole.ADMIN)\n .nullableStatus(UserStatus.ACTIVE)\n .nullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .nullableSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n Optional.of(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n )\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateComplexProfileRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateComplexProfile(\n \"profileId\",\n UpdateComplexProfileRequest\n .builder()\n .nullableRole(UserRole.ADMIN)\n .nullableStatus(UserStatus.ACTIVE)\n .nullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .nullableSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateComplexProfileRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateComplexProfile(\n \"profileId\",\n UpdateComplexProfileRequest\n .builder()\n .nullableRole(UserRole.ADMIN)\n .nullableStatus(UserStatus.ACTIVE)\n .nullableNotification(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .nullableSearchResult(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableArray(\n Arrays.asList(\"nullableArray\", \"nullableArray\")\n )\n .build()\n );\n }\n}\n" } }, { @@ -113,8 +113,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.DeserializationTestRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Organization;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().testDeserialization(\n DeserializationTestRequest\n .builder()\n .requiredString(\"requiredString\")\n .nullableString(\"nullableString\")\n .optionalString(\"optionalString\")\n .optionalNullableString(\"optionalNullableString\")\n .nullableEnum(UserRole.ADMIN)\n .optionalEnum(UserStatus.ACTIVE)\n .nullableUnion(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalUnion(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableList(\n Optional.of(\n Arrays.asList(\"nullableList\", \"nullableList\")\n )\n )\n .nullableMap(\n new HashMap() {{\n put(\"nullableMap\", 1);\n }}\n )\n .nullableObject(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .optionalObject(\n Organization\n .builder()\n .id(\"id\")\n .name(\"name\")\n .domain(\"domain\")\n .employeeCount(1)\n .build()\n )\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.DeserializationTestRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Organization;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().testDeserialization(\n DeserializationTestRequest\n .builder()\n .requiredString(\"requiredString\")\n .nullableString(\"nullableString\")\n .optionalString(\"optionalString\")\n .optionalNullableString(\"optionalNullableString\")\n .nullableEnum(UserRole.ADMIN)\n .optionalEnum(UserStatus.ACTIVE)\n .nullableUnion(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalUnion(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableList(\n Optional.of(\n Arrays.asList(\"nullableList\", \"nullableList\")\n )\n )\n .nullableMap(\n new HashMap() {{\n put(\"nullableMap\", 1);\n }}\n )\n .nullableObject(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .optionalObject(\n Organization\n .builder()\n .id(\"id\")\n .name(\"name\")\n .domain(\"domain\")\n .employeeCount(1)\n .build()\n )\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.DeserializationTestRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Organization;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().testDeserialization(\n DeserializationTestRequest\n .builder()\n .requiredString(\"requiredString\")\n .nullableString(\"nullableString\")\n .optionalString(\"optionalString\")\n .optionalNullableString(\"optionalNullableString\")\n .nullableEnum(UserRole.ADMIN)\n .optionalEnum(UserStatus.ACTIVE)\n .nullableUnion(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalUnion(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableList(\n Arrays.asList(\"nullableList\", \"nullableList\")\n )\n .nullableMap(\n new HashMap() {{\n put(\"nullableMap\", 1);\n }}\n )\n .nullableObject(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .optionalObject(\n Organization\n .builder()\n .id(\"id\")\n .name(\"name\")\n .domain(\"domain\")\n .employeeCount(1)\n .build()\n )\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Address;\nimport com.seed.nullableOptional.resources.nullableoptional.types.DeserializationTestRequest;\nimport com.seed.nullableOptional.resources.nullableoptional.types.EmailNotification;\nimport com.seed.nullableOptional.resources.nullableoptional.types.NotificationMethod;\nimport com.seed.nullableOptional.resources.nullableoptional.types.Organization;\nimport com.seed.nullableOptional.resources.nullableoptional.types.SearchResult;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserResponse;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserRole;\nimport com.seed.nullableOptional.resources.nullableoptional.types.UserStatus;\nimport java.time.OffsetDateTime;\nimport java.util.Arrays;\nimport java.util.HashMap;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().testDeserialization(\n DeserializationTestRequest\n .builder()\n .requiredString(\"requiredString\")\n .nullableString(\"nullableString\")\n .optionalString(\"optionalString\")\n .optionalNullableString(\"optionalNullableString\")\n .nullableEnum(UserRole.ADMIN)\n .optionalEnum(UserStatus.ACTIVE)\n .nullableUnion(\n NotificationMethod.email(\n EmailNotification\n .builder()\n .emailAddress(\"emailAddress\")\n .subject(\"subject\")\n .htmlContent(\"htmlContent\")\n .build()\n )\n )\n .optionalUnion(\n SearchResult.user(\n UserResponse\n .builder()\n .id(\"id\")\n .username(\"username\")\n .createdAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .email(\"email\")\n .phone(\"phone\")\n .updatedAt(OffsetDateTime.parse(\"2024-01-15T09:30:00Z\"))\n .address(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .build()\n )\n )\n .nullableList(\n Arrays.asList(\"nullableList\", \"nullableList\")\n )\n .nullableMap(\n new HashMap() {{\n put(\"nullableMap\", 1);\n }}\n )\n .nullableObject(\n Address\n .builder()\n .street(\"street\")\n .zipCode(\"zipCode\")\n .city(\"city\")\n .state(\"state\")\n .country(\"country\")\n .buildingId(\"buildingId\")\n .tenantId(\"tenantId\")\n .build()\n )\n .optionalObject(\n Organization\n .builder()\n .id(\"id\")\n .name(\"name\")\n .domain(\"domain\")\n .employeeCount(1)\n .build()\n )\n .build()\n );\n }\n}\n" } }, { @@ -152,8 +152,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateTagsRequest;\nimport java.util.Arrays;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateTags(\n \"userId\",\n UpdateTagsRequest\n .builder()\n .tags(\n Optional.of(\n Arrays.asList(\"tags\", \"tags\")\n )\n )\n .categories(\n Optional.of(\n Arrays.asList(\"categories\", \"categories\")\n )\n )\n .labels(\n Optional.of(\n Arrays.asList(\"labels\", \"labels\")\n )\n )\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateTagsRequest;\nimport java.util.Arrays;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateTags(\n \"userId\",\n UpdateTagsRequest\n .builder()\n .tags(\n Optional.of(\n Arrays.asList(\"tags\", \"tags\")\n )\n )\n .categories(\n Optional.of(\n Arrays.asList(\"categories\", \"categories\")\n )\n )\n .labels(\n Optional.of(\n Arrays.asList(\"labels\", \"labels\")\n )\n )\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateTagsRequest;\nimport java.util.Arrays;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateTags(\n \"userId\",\n UpdateTagsRequest\n .builder()\n .tags(\n Arrays.asList(\"tags\", \"tags\")\n )\n .categories(\n Optional.of(\n Arrays.asList(\"categories\", \"categories\")\n )\n )\n .labels(\n Arrays.asList(\"labels\", \"labels\")\n )\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.UpdateTagsRequest;\nimport java.util.Arrays;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().updateTags(\n \"userId\",\n UpdateTagsRequest\n .builder()\n .tags(\n Arrays.asList(\"tags\", \"tags\")\n )\n .categories(\n Optional.of(\n Arrays.asList(\"categories\", \"categories\")\n )\n )\n .labels(\n Arrays.asList(\"labels\", \"labels\")\n )\n .build()\n );\n }\n}\n" } }, { @@ -165,8 +165,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchRequest;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().getSearchResults(\n SearchRequest\n .builder()\n .query(\"query\")\n .includeTypes(\n Optional.of(\n Arrays.asList(\"includeTypes\", \"includeTypes\")\n )\n )\n .filters(\n new HashMap>() {{\n put(\"filters\", Optional.of(\"filters\"));\n }}\n )\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchRequest;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().getSearchResults(\n SearchRequest\n .builder()\n .query(\"query\")\n .includeTypes(\n Optional.of(\n Arrays.asList(\"includeTypes\", \"includeTypes\")\n )\n )\n .filters(\n new HashMap>() {{\n put(\"filters\", Optional.of(\"filters\"));\n }}\n )\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchRequest;\nimport java.util.Arrays;\nimport java.util.HashMap;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().getSearchResults(\n SearchRequest\n .builder()\n .query(\"query\")\n .includeTypes(\n Arrays.asList(\"includeTypes\", \"includeTypes\")\n )\n .filters(\n new HashMap() {{\n put(\"filters\", \"filters\");\n }}\n )\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.nullableOptional.SeedNullableOptionalClient;\nimport com.seed.nullableOptional.resources.nullableoptional.requests.SearchRequest;\nimport java.util.Arrays;\nimport java.util.HashMap;\n\npublic class Example {\n public static void main(String[] args) {\n SeedNullableOptionalClient client = SeedNullableOptionalClient\n .builder()\n .build();\n\n client.nullableOptional().getSearchResults(\n SearchRequest\n .builder()\n .query(\"query\")\n .includeTypes(\n Arrays.asList(\"includeTypes\", \"includeTypes\")\n )\n .filters(\n new HashMap() {{\n put(\"filters\", \"filters\");\n }}\n )\n .build()\n );\n }\n}\n" } } ], diff --git a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/seed/nullableOptional/resources/nullableoptional/requests/FilterByRoleRequest.java b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/seed/nullableOptional/resources/nullableoptional/requests/FilterByRoleRequest.java index dc719b696045..96b866f5395b 100644 --- a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/seed/nullableOptional/resources/nullableoptional/requests/FilterByRoleRequest.java +++ b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/seed/nullableOptional/resources/nullableoptional/requests/FilterByRoleRequest.java @@ -125,7 +125,6 @@ public Builder from(FilterByRoleRequest other) { return this; } - @java.lang.Override @JsonSetter("role") public Builder role(@Nullable UserRole role) { this.role = role; diff --git a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example11.java b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example11.java index 7f1c71419c5a..8ce17380af54 100644 --- a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example11.java +++ b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example11.java @@ -14,9 +14,9 @@ public static void main(String[] args) { .updateTags( "userId", UpdateTagsRequest.builder() - .tags(Optional.of(Arrays.asList("tags", "tags"))) + .tags(Arrays.asList("tags", "tags")) .categories(Optional.of(Arrays.asList("categories", "categories"))) - .labels(Optional.of(Arrays.asList("labels", "labels"))) + .labels(Arrays.asList("labels", "labels")) .build()); } } diff --git a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example12.java b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example12.java index 524dfdff3f98..f09aa7e7ee0a 100644 --- a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example12.java +++ b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example12.java @@ -4,7 +4,6 @@ import com.seed.nullableOptional.resources.nullableoptional.requests.SearchRequest; import java.util.Arrays; import java.util.HashMap; -import java.util.Optional; public class Example12 { public static void main(String[] args) { @@ -14,10 +13,10 @@ public static void main(String[] args) { client.nullableOptional() .getSearchResults(SearchRequest.builder() .query("query") - .includeTypes(Optional.of(Arrays.asList("includeTypes", "includeTypes"))) - .filters(new HashMap>() { + .includeTypes(Arrays.asList("includeTypes", "includeTypes")) + .filters(new HashMap() { { - put("filters", Optional.of("filters")); + put("filters", "filters"); } }) .build()); diff --git a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example5.java b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example5.java index a7f55c9bc6db..78288d7538e2 100644 --- a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example5.java +++ b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example5.java @@ -77,28 +77,26 @@ public static void main(String[] args) { .tenantId("tenantId") .build()) .build())) - .nullableArray(Optional.of(Arrays.asList("nullableArray", "nullableArray"))) + .nullableArray(Arrays.asList("nullableArray", "nullableArray")) .optionalArray(Optional.of(Arrays.asList("optionalArray", "optionalArray"))) - .optionalNullableArray( - Optional.of(Arrays.asList("optionalNullableArray", "optionalNullableArray"))) - .nullableListOfNullables(Optional.of(Arrays.asList( - Optional.of("nullableListOfNullables"), Optional.of("nullableListOfNullables")))) - .nullableMapOfNullables(new HashMap>() { + .optionalNullableArray(Arrays.asList("optionalNullableArray", "optionalNullableArray")) + .nullableListOfNullables(Arrays.asList("nullableListOfNullables", "nullableListOfNullables")) + .nullableMapOfNullables(new HashMap() { { put( "nullableMapOfNullables", - Optional.of(Address.builder() + Address.builder() .street("street") .zipCode("zipCode") - .city(Optional.of("city")) + .city("city") .state(Optional.of("state")) .country(Optional.of("country")) - .buildingId(Optional.of("buildingId")) + .buildingId("buildingId") .tenantId(Optional.of("tenantId")) - .build())); + .build()); } }) - .nullableListOfUnions(Optional.of(Arrays.asList( + .nullableListOfUnions(Arrays.asList( NotificationMethod.email(EmailNotification.builder() .emailAddress("emailAddress") .subject("subject") @@ -108,7 +106,7 @@ public static void main(String[] args) { .emailAddress("emailAddress") .subject("subject") .htmlContent("htmlContent") - .build())))) + .build()))) .optionalMapOfEnums(new HashMap() { { put("optionalMapOfEnums", UserRole.ADMIN); diff --git a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example7.java b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example7.java index ab6405eecce7..0ca39271b186 100644 --- a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example7.java +++ b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example7.java @@ -11,7 +11,6 @@ import com.seed.nullableOptional.resources.nullableoptional.types.UserStatus; import java.time.OffsetDateTime; import java.util.Arrays; -import java.util.Optional; public class Example7 { public static void main(String[] args) { @@ -46,7 +45,7 @@ public static void main(String[] args) { .tenantId("tenantId") .build()) .build())) - .nullableArray(Optional.of(Arrays.asList("nullableArray", "nullableArray"))) + .nullableArray(Arrays.asList("nullableArray", "nullableArray")) .build()); } } diff --git a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example8.java b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example8.java index 25a322b8faad..7293ca00b771 100644 --- a/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example8.java +++ b/seed/java-sdk/nullable-optional/with-nullable-annotation/src/main/java/com/snippets/Example8.java @@ -13,7 +13,6 @@ import java.time.OffsetDateTime; import java.util.Arrays; import java.util.HashMap; -import java.util.Optional; public class Example8 { public static void main(String[] args) { @@ -50,7 +49,7 @@ public static void main(String[] args) { .tenantId("tenantId") .build()) .build())) - .nullableList(Optional.of(Arrays.asList("nullableList", "nullableList"))) + .nullableList(Arrays.asList("nullableList", "nullableList")) .nullableMap(new HashMap() { { put("nullableMap", 1); diff --git a/seed/java-sdk/optional/wire-tests/reference.md b/seed/java-sdk/optional/wire-tests/reference.md index 23ca8c759aad..eea41dd391ef 100644 --- a/seed/java-sdk/optional/wire-tests/reference.md +++ b/seed/java-sdk/optional/wire-tests/reference.md @@ -126,10 +126,12 @@ This should not generate wire tests expecting {} when Optional.empty() is passed client.optional().sendOptionalNullableWithAllOptionalProperties( "actionId", "id", - DeployParams - .builder() - .updateDraft(true) - .build() + Optional.of( + DeployParams + .builder() + .updateDraft(true) + .build() + ) ); ``` diff --git a/seed/java-sdk/optional/wire-tests/snippet.json b/seed/java-sdk/optional/wire-tests/snippet.json index 0288236b877c..6e4ca45f4d56 100644 --- a/seed/java-sdk/optional/wire-tests/snippet.json +++ b/seed/java-sdk/optional/wire-tests/snippet.json @@ -35,8 +35,8 @@ }, "snippet": { "type": "java", - "sync_client": "package com.example.usage;\n\nimport com.seed.objectsWithImports.SeedObjectsWithImportsClient;\nimport com.seed.objectsWithImports.resources.optional.types.DeployParams;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectsWithImportsClient client = SeedObjectsWithImportsClient\n .builder()\n .build();\n\n client.optional().sendOptionalNullableWithAllOptionalProperties(\n \"actionId\",\n \"id\",\n DeployParams\n .builder()\n .updateDraft(true)\n .build()\n );\n }\n}\n", - "async_client": "package com.example.usage;\n\nimport com.seed.objectsWithImports.SeedObjectsWithImportsClient;\nimport com.seed.objectsWithImports.resources.optional.types.DeployParams;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectsWithImportsClient client = SeedObjectsWithImportsClient\n .builder()\n .build();\n\n client.optional().sendOptionalNullableWithAllOptionalProperties(\n \"actionId\",\n \"id\",\n DeployParams\n .builder()\n .updateDraft(true)\n .build()\n );\n }\n}\n" + "sync_client": "package com.example.usage;\n\nimport com.seed.objectsWithImports.SeedObjectsWithImportsClient;\nimport com.seed.objectsWithImports.resources.optional.types.DeployParams;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectsWithImportsClient client = SeedObjectsWithImportsClient\n .builder()\n .build();\n\n client.optional().sendOptionalNullableWithAllOptionalProperties(\n \"actionId\",\n \"id\",\n Optional.of(\n DeployParams\n .builder()\n .updateDraft(true)\n .build()\n )\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.objectsWithImports.SeedObjectsWithImportsClient;\nimport com.seed.objectsWithImports.resources.optional.types.DeployParams;\nimport java.util.Optional;\n\npublic class Example {\n public static void main(String[] args) {\n SeedObjectsWithImportsClient client = SeedObjectsWithImportsClient\n .builder()\n .build();\n\n client.optional().sendOptionalNullableWithAllOptionalProperties(\n \"actionId\",\n \"id\",\n Optional.of(\n DeployParams\n .builder()\n .updateDraft(true)\n .build()\n )\n );\n }\n}\n" } } ], diff --git a/seed/java-sdk/optional/wire-tests/src/main/java/com/snippets/Example2.java b/seed/java-sdk/optional/wire-tests/src/main/java/com/snippets/Example2.java index f934233ac8ed..dc224d1af212 100644 --- a/seed/java-sdk/optional/wire-tests/src/main/java/com/snippets/Example2.java +++ b/seed/java-sdk/optional/wire-tests/src/main/java/com/snippets/Example2.java @@ -2,6 +2,7 @@ import com.seed.objectsWithImports.SeedObjectsWithImportsClient; import com.seed.objectsWithImports.resources.optional.types.DeployParams; +import java.util.Optional; public class Example2 { public static void main(String[] args) { @@ -13,6 +14,6 @@ public static void main(String[] args) { .sendOptionalNullableWithAllOptionalProperties( "actionId", "id", - DeployParams.builder().updateDraft(true).build()); + Optional.of(DeployParams.builder().updateDraft(true).build())); } } diff --git a/seed/java-sdk/optional/wire-tests/src/test/java/com/seed/objectsWithImports/OptionalWireTest.java b/seed/java-sdk/optional/wire-tests/src/test/java/com/seed/objectsWithImports/OptionalWireTest.java index eb4fe7a88aac..0105ea2184b7 100644 --- a/seed/java-sdk/optional/wire-tests/src/test/java/com/seed/objectsWithImports/OptionalWireTest.java +++ b/seed/java-sdk/optional/wire-tests/src/test/java/com/seed/objectsWithImports/OptionalWireTest.java @@ -196,7 +196,7 @@ public void testSendOptionalNullableWithAllOptionalProperties() throws Exception .sendOptionalNullableWithAllOptionalProperties( "actionId", "id", - DeployParams.builder().updateDraft(true).build()); + Optional.of(DeployParams.builder().updateDraft(true).build())); RecordedRequest request = server.takeRequest(); Assertions.assertNotNull(request); Assertions.assertEquals("POST", request.getMethod()); diff --git a/seed/java-sdk/request-parameters/src/main/java/com/snippets/Example3.java b/seed/java-sdk/request-parameters/src/main/java/com/snippets/Example3.java index cfa6f7a34d33..d6df3d2bceca 100644 --- a/seed/java-sdk/request-parameters/src/main/java/com/snippets/Example3.java +++ b/seed/java-sdk/request-parameters/src/main/java/com/snippets/Example3.java @@ -2,6 +2,7 @@ import com.seed.requestParameters.SeedRequestParametersClient; import com.seed.requestParameters.resources.user.types.CreateUsernameBodyOptionalProperties; +import java.util.Optional; public class Example3 { public static void main(String[] args) { @@ -10,10 +11,10 @@ public static void main(String[] args) { .build(); client.user() - .createUsernameOptional(CreateUsernameBodyOptionalProperties.builder() + .createUsernameOptional(Optional.of(CreateUsernameBodyOptionalProperties.builder() .username("username") .password("password") .name("test") - .build()); + .build())); } } diff --git a/seed/java-sdk/seed.yml b/seed/java-sdk/seed.yml index 8750e13f98f6..6e1dcd0cade4 100644 --- a/seed/java-sdk/seed.yml +++ b/seed/java-sdk/seed.yml @@ -391,12 +391,7 @@ allowedFailures: - examples:no-custom-config - examples:readme-config - exhaustive:local-files - - java-inline-types:no-wrapped-aliases - - nullable-optional:with-nullable-annotation - - nullable-optional:collapse-optional-nullable - oauth-client-credentials-custom - - request-parameters - - streaming-parameter - inferred-auth-implicit-reference # Generated raw client / publish fixtures fail to compile in CI @@ -408,8 +403,6 @@ allowedFailures: # Snippet failures; many of these failures are due to the fact that a # required list of query parameters is not actually required by the builder. - - java-inline-types:inline - - java-inline-types:enable-forward-compatible-enums - nullable:wrapped-aliases - pagination-custom diff --git a/seed/java-sdk/streaming-parameter/.fern/metadata.json b/seed/java-sdk/streaming-parameter/.fern/metadata.json new file mode 100644 index 000000000000..8558dfdb1357 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/.fern/metadata.json @@ -0,0 +1,10 @@ +{ + "cliVersion": "DUMMY", + "generatorName": "fernapi/fern-java-sdk", + "generatorVersion": "local", + "originGitCommit": "DUMMY", + "invokedBy": "ci", + "requestedVersion": "0.0.1", + "ciProvider": "github", + "sdkVersion": "0.0.1" +} \ No newline at end of file diff --git a/seed/java-sdk/streaming-parameter/.github/workflows/ci.yml b/seed/java-sdk/streaming-parameter/.github/workflows/ci.yml new file mode 100644 index 000000000000..09c8c666ad73 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/.github/workflows/ci.yml @@ -0,0 +1,65 @@ +name: ci + +on: [push] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +jobs: + compile: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Set up Java + id: setup-jre + uses: actions/setup-java@v1 + with: + java-version: "11" + architecture: x64 + + - name: Compile + run: ./gradlew compileJava + + test: + needs: [ compile ] + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Set up Java + id: setup-jre + uses: actions/setup-java@v1 + with: + java-version: "11" + architecture: x64 + + - name: Test + run: ./gradlew test + publish: + needs: [ compile, test ] + if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Set up Java + id: setup-jre + uses: actions/setup-java@v1 + with: + java-version: "11" + architecture: x64 + + - name: Publish to maven + run: | + ./gradlew publish + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + MAVEN_PUBLISH_REGISTRY_URL: "" diff --git a/seed/java-sdk/streaming-parameter/.gitignore b/seed/java-sdk/streaming-parameter/.gitignore new file mode 100644 index 000000000000..d4199abc2cd4 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/.gitignore @@ -0,0 +1,24 @@ +*.class +.project +.gradle +? +.classpath +.checkstyle +.settings +.node +build + +# IntelliJ +*.iml +*.ipr +*.iws +.idea/ +out/ + +# Eclipse/IntelliJ APT +generated_src/ +generated_testSrc/ +generated/ + +bin +build \ No newline at end of file diff --git a/seed/java-sdk/streaming-parameter/CONTRIBUTING.md b/seed/java-sdk/streaming-parameter/CONTRIBUTING.md new file mode 100644 index 000000000000..24cf9fa0c645 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/CONTRIBUTING.md @@ -0,0 +1,114 @@ +# Contributing + +Thanks for your interest in contributing to this SDK! This document provides guidelines for contributing to the project. + +## Getting Started + +### Prerequisites + +- Java 11+ +- Gradle + +### Installation + +Install the project dependencies: + +```bash +./gradlew build +``` + +### Building + +Build the project: + +```bash +./gradlew build +``` + +### Testing + +Run the test suite: + +```bash +./gradlew test +``` + +### Formatting + +Check and fix code style: + +```bash +./gradlew spotlessApply +``` + +## About Generated Code + +**Important**: Most files in this SDK are automatically generated by [Fern](https://buildwithfern.com) from the API definition. Direct modifications to generated files will be overwritten the next time the SDK is generated. + +### Generated Files + +The following directories contain generated code: +- `src/` - API client classes and types +- Most Java files in the project + +### How to Customize + +If you need to customize the SDK, you have two options: + +#### Option 1: Use `.fernignore` + +For custom code that should persist across SDK regenerations: + +1. Create a `.fernignore` file in the project root +2. Add file patterns for files you want to preserve (similar to `.gitignore` syntax) +3. Add your custom code to those files + +Files listed in `.fernignore` will not be overwritten when the SDK is regenerated. + +For more information, see the [Fern documentation on custom code](https://buildwithfern.com/learn/sdks/overview/custom-code). + +#### Option 2: Contribute to the Generator + +If you want to change how code is generated for all users of this SDK: + +1. The Java SDK generator lives in the [Fern repository](https://github.com/fern-api/fern) +2. Generator code is located at `generators/java-v2/` +3. Follow the [Fern contributing guidelines](https://github.com/fern-api/fern/blob/main/CONTRIBUTING.md) +4. Submit a pull request with your changes to the generator + +This approach is best for: +- Bug fixes in generated code +- New features that would benefit all users +- Improvements to code generation patterns + +## Making Changes + +### Workflow + +1. Create a new branch for your changes +2. Make your modifications +3. Run tests to ensure nothing breaks: `./gradlew test` +4. Run formatting: `./gradlew spotlessApply` +5. Build the project: `./gradlew build` +6. Commit your changes with a clear commit message +7. Push your branch and create a pull request + +### Commit Messages + +Write clear, descriptive commit messages that explain what changed and why. + +### Code Style + +This project uses automated code formatting. Run `./gradlew spotlessApply` before committing to ensure your code meets the project's style guidelines. + +## Questions or Issues? + +If you have questions or run into issues: + +1. Check the [Fern documentation](https://buildwithfern.com) +2. Search existing [GitHub issues](https://github.com/fern-api/fern/issues) +3. Open a new issue if your question hasn't been addressed + +## License + +By contributing to this project, you agree that your contributions will be licensed under the same license as the project. diff --git a/seed/java-sdk/streaming-parameter/README.md b/seed/java-sdk/streaming-parameter/README.md new file mode 100644 index 000000000000..718185e4edab --- /dev/null +++ b/seed/java-sdk/streaming-parameter/README.md @@ -0,0 +1,227 @@ +# Seed Java Library + +[![fern shield](https://img.shields.io/badge/%F0%9F%8C%BF-Built%20with%20Fern-brightgreen)](https://buildwithfern.com?utm_source=github&utm_medium=github&utm_campaign=readme&utm_source=Seed%2FJava) +[![Maven Central](https://img.shields.io/maven-central/v/com.fern/streaming-parameter)](https://central.sonatype.com/artifact/com.fern/streaming-parameter) + +The Seed Java library provides convenient access to the Seed APIs from Java. + +## Table of Contents + +- [Installation](#installation) +- [Reference](#reference) +- [Usage](#usage) +- [Base Url](#base-url) +- [Exception Handling](#exception-handling) +- [Advanced](#advanced) + - [Custom Client](#custom-client) + - [Retries](#retries) + - [Timeouts](#timeouts) + - [Custom Headers](#custom-headers) + - [Access Raw Response Data](#access-raw-response-data) +- [Contributing](#contributing) + +## Installation + +### Gradle + +Add the dependency in your `build.gradle` file: + +```groovy +dependencies { + implementation 'com.fern:streaming-parameter:0.0.1' +} +``` + +### Maven + +Add the dependency in your `pom.xml` file: + +```xml + + com.fern + streaming-parameter + 0.0.1 + +``` + +## Reference + +A full reference for this library is available [here](./reference.md). + +## Usage + +Instantiate and use the client with the following: + +```java +package com.example.usage; + +import com.seed.streaming.SeedStreamingClient; +import com.seed.streaming.resources.dummy.requests.GenerateRequest; + +public class Example { + public static void main(String[] args) { + SeedStreamingClient client = SeedStreamingClient + .builder() + .build(); + + client.dummy().generate( + GenerateRequest + .builder() + .stream(false) + .numEvents(5) + .build() + ); + } +} +``` + +## Base Url + +You can set a custom base URL when constructing the client. + +```java +import com.seed.streaming.SeedStreamingClient; + +SeedStreamingClient client = SeedStreamingClient + .builder() + .url("https://example.com") + .build(); +``` + +## Exception Handling + +When the API returns a non-success status code (4xx or 5xx response), an API exception will be thrown. + +```java +import com.seed.streaming.core.SeedStreamingApiException; + +try{ + client.dummy().generate(...); +} catch (SeedStreamingApiException e){ + // Do something with the API exception... +} +``` + +## Advanced + +### Custom Client + +This SDK is built to work with any instance of `OkHttpClient`. By default, if no client is provided, the SDK will construct one. +However, you can pass your own client like so: + +```java +import com.seed.streaming.SeedStreamingClient; +import okhttp3.OkHttpClient; + +OkHttpClient customClient = ...; + +SeedStreamingClient client = SeedStreamingClient + .builder() + .httpClient(customClient) + .build(); +``` + +### Retries + +The SDK is instrumented with automatic retries with exponential backoff. A request will be retried as long +as the request is deemed retryable and the number of retry attempts has not grown larger than the configured +retry limit (default: 2). Before defaulting to exponential backoff, the SDK will first attempt to respect +the `Retry-After` header (as either in seconds or as an HTTP date), and then the `X-RateLimit-Reset` header +(as a Unix timestamp in epoch seconds); failing both of those, it will fall back to exponential backoff. + +Which status codes are retried depends on the `retry-status-codes` generator configuration: + +**`legacy`** (current default): retries on +- [408](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) (Timeout) +- [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) (Too Many Requests) +- [5XX](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses) (All server errors, including 500) + +**`recommended`**: retries on +- [408](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) (Timeout) +- [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) (Too Many Requests) +- [502](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502) (Bad Gateway) +- [503](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503) (Service Unavailable) +- [504](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504) (Gateway Timeout) + +Use the `maxRetries` client option to configure this behavior. + +```java +import com.seed.streaming.SeedStreamingClient; + +SeedStreamingClient client = SeedStreamingClient + .builder() + .maxRetries(1) + .build(); +``` + +### Timeouts + +The SDK defaults to a 60 second timeout. You can configure this with a timeout option at the client or request level. +```java +import com.seed.streaming.SeedStreamingClient; +import com.seed.streaming.core.RequestOptions; + +// Client level +SeedStreamingClient client = SeedStreamingClient + .builder() + .timeout(60) + .build(); + +// Request level +client.dummy().generate( + ..., + RequestOptions + .builder() + .timeout(60) + .build() +); +``` + +### Custom Headers + +The SDK allows you to add custom headers to requests. You can configure headers at the client level or at the request level. + +```java +import com.seed.streaming.SeedStreamingClient; +import com.seed.streaming.core.RequestOptions; + +// Client level +SeedStreamingClient client = SeedStreamingClient + .builder() + .addHeader("X-Custom-Header", "custom-value") + .addHeader("X-Request-Id", "abc-123") + .build(); +; + +// Request level +client.dummy().generate( + ..., + RequestOptions + .builder() + .addHeader("X-Request-Header", "request-value") + .build() +); +``` + +### Access Raw Response Data + +The SDK provides access to raw response data, including headers, through the `withRawResponse()` method. +The `withRawResponse()` method returns a raw client that wraps all responses with `body()` and `headers()` methods. +(A normal client's `response` is identical to a raw client's `response.body()`.) + +```java +SeedStreamingHttpResponse response = client.dummy().withRawResponse().generate(...); + +System.out.println(response.body()); +System.out.println(response.headers().get("X-My-Header")); +``` + +## Contributing + +While we value open-source contributions to this SDK, this library is generated programmatically. +Additions made directly to this library would have to be moved over to our generation code, +otherwise they would be overwritten upon the next generated release. Feel free to open a PR as +a proof of concept, but know that we will not be able to merge it as-is. We suggest opening +an issue first to discuss with us! + +On the other hand, contributions to the README are always very welcome! diff --git a/seed/java-sdk/streaming-parameter/build.gradle b/seed/java-sdk/streaming-parameter/build.gradle new file mode 100644 index 000000000000..1b7c1475d246 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/build.gradle @@ -0,0 +1,102 @@ +plugins { + id 'java-library' + id 'maven-publish' + id 'com.diffplug.spotless' version '6.11.0' +} + +repositories { + mavenCentral() + maven { + url 'https://s01.oss.sonatype.org/content/repositories/releases/' + } +} + +dependencies { + api 'com.squareup.okhttp3:okhttp:5.2.1' + api 'com.fasterxml.jackson.core:jackson-databind:2.18.6' + api 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.6' + api 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.6' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' + testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.2' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.2' +} + + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +tasks.withType(Javadoc) { + failOnError false + options.addStringOption('Xdoclint:none', '-quiet') +} + +spotless { + java { + palantirJavaFormat() + } +} + + +java { + withSourcesJar() + withJavadocJar() +} + + +group = 'com.fern' + +version = '0.0.1' + +jar { + dependsOn(":generatePomFileForMavenPublication") + archiveBaseName = "streaming-parameter" +} + +sourcesJar { + archiveBaseName = "streaming-parameter" +} + +javadocJar { + archiveBaseName = "streaming-parameter" +} + +test { + useJUnitPlatform() + testLogging { + showStandardStreams = true + } +} + +publishing { + publications { + maven(MavenPublication) { + groupId = 'com.fern' + artifactId = 'streaming-parameter' + version = '0.0.1' + from components.java + pom { + licenses { + license { + name = 'The MIT License (MIT)' + url = 'https://mit-license.org/' + } + } + scm { + connection = 'scm:git:git://github.com/streaming-parameter/fern.git' + developerConnection = 'scm:git:git://github.com/streaming-parameter/fern.git' + url = 'https://github.com/streaming-parameter/fern' + } + } + } + } + repositories { + maven { + url "$System.env.MAVEN_PUBLISH_REGISTRY_URL" + credentials { + username "$System.env.MAVEN_USERNAME" + password "$System.env.MAVEN_PASSWORD" + } + } + } +} + diff --git a/seed/java-sdk/streaming-parameter/reference.md b/seed/java-sdk/streaming-parameter/reference.md new file mode 100644 index 000000000000..27b1d3dfb9e2 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/reference.md @@ -0,0 +1,56 @@ +# Reference +## Dummy +
client.dummy.generate(request) -> Iterable&lt;StreamResponse&gt; +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```java +client.dummy().generate( + GenerateRequest + .builder() + .stream(false) + .numEvents(5) + .build() +); +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**stream:** `Boolean` + +
+
+ +
+
+ +**numEvents:** `Integer` + +
+
+
+
+ + +
+
+
+ diff --git a/seed/java-sdk/streaming-parameter/sample-app/build.gradle b/seed/java-sdk/streaming-parameter/sample-app/build.gradle new file mode 100644 index 000000000000..4ee8f227b7af --- /dev/null +++ b/seed/java-sdk/streaming-parameter/sample-app/build.gradle @@ -0,0 +1,19 @@ +plugins { + id 'java-library' +} + +repositories { + mavenCentral() + maven { + url 'https://s01.oss.sonatype.org/content/repositories/releases/' + } +} + +dependencies { + implementation rootProject +} + + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + diff --git a/seed/java-sdk/streaming-parameter/sample-app/src/main/java/sample/App.java b/seed/java-sdk/streaming-parameter/sample-app/src/main/java/sample/App.java new file mode 100644 index 000000000000..590cde5533a2 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/sample-app/src/main/java/sample/App.java @@ -0,0 +1,13 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +package sample; + +import java.lang.String; + +public final class App { + public static void main(String[] args) { + // import com.seed.streaming.AsyncSeedStreamingClient + } +} diff --git a/seed/java-sdk/streaming-parameter/settings.gradle b/seed/java-sdk/streaming-parameter/settings.gradle new file mode 100644 index 000000000000..ce2a3c5c1dce --- /dev/null +++ b/seed/java-sdk/streaming-parameter/settings.gradle @@ -0,0 +1,3 @@ +rootProject.name = 'streaming-parameter' + +include 'sample-app' \ No newline at end of file diff --git a/seed/java-sdk/streaming-parameter/snippet-templates.json b/seed/java-sdk/streaming-parameter/snippet-templates.json deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/seed/java-sdk/streaming-parameter/snippet.json b/seed/java-sdk/streaming-parameter/snippet.json index e69de29bb2d1..654f90a660e1 100644 --- a/seed/java-sdk/streaming-parameter/snippet.json +++ b/seed/java-sdk/streaming-parameter/snippet.json @@ -0,0 +1,18 @@ +{ + "endpoints": [ + { + "example_identifier": "Default", + "id": { + "method": "POST", + "path": "/generate", + "identifier_override": "endpoint_dummy.generate" + }, + "snippet": { + "type": "java", + "sync_client": "package com.example.usage;\n\nimport com.seed.streaming.SeedStreamingClient;\nimport com.seed.streaming.resources.dummy.requests.GenerateRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedStreamingClient client = SeedStreamingClient\n .builder()\n .build();\n\n client.dummy().generate(\n GenerateRequest\n .builder()\n .stream(false)\n .numEvents(5)\n .build()\n );\n }\n}\n", + "async_client": "package com.example.usage;\n\nimport com.seed.streaming.SeedStreamingClient;\nimport com.seed.streaming.resources.dummy.requests.GenerateRequest;\n\npublic class Example {\n public static void main(String[] args) {\n SeedStreamingClient client = SeedStreamingClient\n .builder()\n .build();\n\n client.dummy().generate(\n GenerateRequest\n .builder()\n .stream(false)\n .numEvents(5)\n .build()\n );\n }\n}\n" + } + } + ], + "types": {} +} \ No newline at end of file diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/AsyncSeedStreamingClient.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/AsyncSeedStreamingClient.java new file mode 100644 index 000000000000..8c482cb56b45 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/AsyncSeedStreamingClient.java @@ -0,0 +1,28 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming; + +import com.seed.streaming.core.ClientOptions; +import com.seed.streaming.core.Suppliers; +import com.seed.streaming.resources.dummy.AsyncDummyClient; +import java.util.function.Supplier; + +public class AsyncSeedStreamingClient { + protected final ClientOptions clientOptions; + + protected final Supplier dummyClient; + + public AsyncSeedStreamingClient(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + this.dummyClient = Suppliers.memoize(() -> new AsyncDummyClient(clientOptions)); + } + + public AsyncDummyClient dummy() { + return this.dummyClient.get(); + } + + public static AsyncSeedStreamingClientBuilder builder() { + return new AsyncSeedStreamingClientBuilder(); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/AsyncSeedStreamingClientBuilder.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/AsyncSeedStreamingClientBuilder.java new file mode 100644 index 000000000000..e458e7d969c4 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/AsyncSeedStreamingClientBuilder.java @@ -0,0 +1,189 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming; + +import com.seed.streaming.core.ClientOptions; +import com.seed.streaming.core.Environment; +import com.seed.streaming.core.LogConfig; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import okhttp3.OkHttpClient; + +public class AsyncSeedStreamingClientBuilder { + private Optional timeout = Optional.empty(); + + private Optional maxRetries = Optional.empty(); + + private final Map customHeaders = new HashMap<>(); + + private Environment environment; + + private OkHttpClient httpClient; + + private Optional logging = Optional.empty(); + + public AsyncSeedStreamingClientBuilder url(String url) { + this.environment = Environment.custom(url); + return this; + } + + /** + * Sets the timeout (in seconds) for the client. Defaults to 60 seconds. + */ + public AsyncSeedStreamingClientBuilder timeout(int timeout) { + this.timeout = Optional.of(timeout); + return this; + } + + /** + * Sets the maximum number of retries for the client. Defaults to 2 retries. + */ + public AsyncSeedStreamingClientBuilder maxRetries(int maxRetries) { + this.maxRetries = Optional.of(maxRetries); + return this; + } + + /** + * Sets the underlying OkHttp client + */ + public AsyncSeedStreamingClientBuilder httpClient(OkHttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Configure logging for the SDK. Silent by default — no log output unless explicitly configured. + */ + public AsyncSeedStreamingClientBuilder logging(LogConfig logging) { + this.logging = Optional.of(logging); + return this; + } + + /** + * Add a custom header to be sent with all requests. + * For headers that need to be computed dynamically or conditionally, use the setAdditional() method override instead. + * + * @param name The header name + * @param value The header value + * @return This builder for method chaining + */ + public AsyncSeedStreamingClientBuilder addHeader(String name, String value) { + this.customHeaders.put(name, value); + return this; + } + + protected ClientOptions buildClientOptions() { + ClientOptions.Builder builder = ClientOptions.builder(); + setEnvironment(builder); + setHttpClient(builder); + setTimeouts(builder); + setRetries(builder); + setLogging(builder); + for (Map.Entry header : this.customHeaders.entrySet()) { + builder.addHeader(header.getKey(), header.getValue()); + } + setAdditional(builder); + return builder.build(); + } + + /** + * Sets the environment configuration for the client. + * Override this method to modify URLs or add environment-specific logic. + * + * @param builder The ClientOptions.Builder to configure + */ + protected void setEnvironment(ClientOptions.Builder builder) { + builder.environment(this.environment); + } + + /** + * Sets the request timeout configuration. + * Override this method to customize timeout behavior. + * + * @param builder The ClientOptions.Builder to configure + */ + protected void setTimeouts(ClientOptions.Builder builder) { + if (this.timeout.isPresent()) { + builder.timeout(this.timeout.get()); + } + } + + /** + * Sets the retry configuration for failed requests. + * Override this method to implement custom retry strategies. + * + * @param builder The ClientOptions.Builder to configure + */ + protected void setRetries(ClientOptions.Builder builder) { + if (this.maxRetries.isPresent()) { + builder.maxRetries(this.maxRetries.get()); + } + } + + /** + * Sets the OkHttp client configuration. + * Override this method to customize HTTP client behavior (interceptors, connection pools, etc). + * + * @param builder The ClientOptions.Builder to configure + */ + protected void setHttpClient(ClientOptions.Builder builder) { + if (this.httpClient != null) { + builder.httpClient(this.httpClient); + } + } + + /** + * Sets the logging configuration for the SDK. + * Override this method to customize logging behavior. + * + * @param builder The ClientOptions.Builder to configure + */ + protected void setLogging(ClientOptions.Builder builder) { + if (this.logging.isPresent()) { + builder.logging(this.logging.get()); + } + } + + /** + * Override this method to add any additional configuration to the client. + * This method is called at the end of the configuration chain, allowing you to add + * custom headers, modify settings, or perform any other client customization. + * + * @param builder The ClientOptions.Builder to configure + * + * Example: + *
{@code
+     * @Override
+     * protected void setAdditional(ClientOptions.Builder builder) {
+     *     builder.addHeader("X-Request-ID", () -> UUID.randomUUID().toString());
+     *     builder.addHeader("X-Client-Version", "1.0.0");
+     * }
+     * }
+ */ + protected void setAdditional(ClientOptions.Builder builder) {} + + /** + * Override this method to add custom validation logic before the client is built. + * This method is called at the beginning of the build() method to ensure the configuration is valid. + * Throw an exception to prevent client creation if validation fails. + * + * Example: + *
{@code
+     * @Override
+     * protected void validateConfiguration() {
+     *     super.validateConfiguration(); // Run parent validations
+     *     if (tenantId == null || tenantId.isEmpty()) {
+     *         throw new IllegalStateException("tenantId is required");
+     *     }
+     * }
+     * }
+ */ + protected void validateConfiguration() {} + + public AsyncSeedStreamingClient build() { + validateConfiguration(); + return new AsyncSeedStreamingClient(buildClientOptions()); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/SeedStreamingClient.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/SeedStreamingClient.java new file mode 100644 index 000000000000..02bff4070ba2 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/SeedStreamingClient.java @@ -0,0 +1,28 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming; + +import com.seed.streaming.core.ClientOptions; +import com.seed.streaming.core.Suppliers; +import com.seed.streaming.resources.dummy.DummyClient; +import java.util.function.Supplier; + +public class SeedStreamingClient { + protected final ClientOptions clientOptions; + + protected final Supplier dummyClient; + + public SeedStreamingClient(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + this.dummyClient = Suppliers.memoize(() -> new DummyClient(clientOptions)); + } + + public DummyClient dummy() { + return this.dummyClient.get(); + } + + public static SeedStreamingClientBuilder builder() { + return new SeedStreamingClientBuilder(); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/SeedStreamingClientBuilder.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/SeedStreamingClientBuilder.java new file mode 100644 index 000000000000..bd29398b909a --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/SeedStreamingClientBuilder.java @@ -0,0 +1,189 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming; + +import com.seed.streaming.core.ClientOptions; +import com.seed.streaming.core.Environment; +import com.seed.streaming.core.LogConfig; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import okhttp3.OkHttpClient; + +public class SeedStreamingClientBuilder { + private Optional timeout = Optional.empty(); + + private Optional maxRetries = Optional.empty(); + + private final Map customHeaders = new HashMap<>(); + + private Environment environment; + + private OkHttpClient httpClient; + + private Optional logging = Optional.empty(); + + public SeedStreamingClientBuilder url(String url) { + this.environment = Environment.custom(url); + return this; + } + + /** + * Sets the timeout (in seconds) for the client. Defaults to 60 seconds. + */ + public SeedStreamingClientBuilder timeout(int timeout) { + this.timeout = Optional.of(timeout); + return this; + } + + /** + * Sets the maximum number of retries for the client. Defaults to 2 retries. + */ + public SeedStreamingClientBuilder maxRetries(int maxRetries) { + this.maxRetries = Optional.of(maxRetries); + return this; + } + + /** + * Sets the underlying OkHttp client + */ + public SeedStreamingClientBuilder httpClient(OkHttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Configure logging for the SDK. Silent by default — no log output unless explicitly configured. + */ + public SeedStreamingClientBuilder logging(LogConfig logging) { + this.logging = Optional.of(logging); + return this; + } + + /** + * Add a custom header to be sent with all requests. + * For headers that need to be computed dynamically or conditionally, use the setAdditional() method override instead. + * + * @param name The header name + * @param value The header value + * @return This builder for method chaining + */ + public SeedStreamingClientBuilder addHeader(String name, String value) { + this.customHeaders.put(name, value); + return this; + } + + protected ClientOptions buildClientOptions() { + ClientOptions.Builder builder = ClientOptions.builder(); + setEnvironment(builder); + setHttpClient(builder); + setTimeouts(builder); + setRetries(builder); + setLogging(builder); + for (Map.Entry header : this.customHeaders.entrySet()) { + builder.addHeader(header.getKey(), header.getValue()); + } + setAdditional(builder); + return builder.build(); + } + + /** + * Sets the environment configuration for the client. + * Override this method to modify URLs or add environment-specific logic. + * + * @param builder The ClientOptions.Builder to configure + */ + protected void setEnvironment(ClientOptions.Builder builder) { + builder.environment(this.environment); + } + + /** + * Sets the request timeout configuration. + * Override this method to customize timeout behavior. + * + * @param builder The ClientOptions.Builder to configure + */ + protected void setTimeouts(ClientOptions.Builder builder) { + if (this.timeout.isPresent()) { + builder.timeout(this.timeout.get()); + } + } + + /** + * Sets the retry configuration for failed requests. + * Override this method to implement custom retry strategies. + * + * @param builder The ClientOptions.Builder to configure + */ + protected void setRetries(ClientOptions.Builder builder) { + if (this.maxRetries.isPresent()) { + builder.maxRetries(this.maxRetries.get()); + } + } + + /** + * Sets the OkHttp client configuration. + * Override this method to customize HTTP client behavior (interceptors, connection pools, etc). + * + * @param builder The ClientOptions.Builder to configure + */ + protected void setHttpClient(ClientOptions.Builder builder) { + if (this.httpClient != null) { + builder.httpClient(this.httpClient); + } + } + + /** + * Sets the logging configuration for the SDK. + * Override this method to customize logging behavior. + * + * @param builder The ClientOptions.Builder to configure + */ + protected void setLogging(ClientOptions.Builder builder) { + if (this.logging.isPresent()) { + builder.logging(this.logging.get()); + } + } + + /** + * Override this method to add any additional configuration to the client. + * This method is called at the end of the configuration chain, allowing you to add + * custom headers, modify settings, or perform any other client customization. + * + * @param builder The ClientOptions.Builder to configure + * + * Example: + *
{@code
+     * @Override
+     * protected void setAdditional(ClientOptions.Builder builder) {
+     *     builder.addHeader("X-Request-ID", () -> UUID.randomUUID().toString());
+     *     builder.addHeader("X-Client-Version", "1.0.0");
+     * }
+     * }
+ */ + protected void setAdditional(ClientOptions.Builder builder) {} + + /** + * Override this method to add custom validation logic before the client is built. + * This method is called at the beginning of the build() method to ensure the configuration is valid. + * Throw an exception to prevent client creation if validation fails. + * + * Example: + *
{@code
+     * @Override
+     * protected void validateConfiguration() {
+     *     super.validateConfiguration(); // Run parent validations
+     *     if (tenantId == null || tenantId.isEmpty()) {
+     *         throw new IllegalStateException("tenantId is required");
+     *     }
+     * }
+     * }
+ */ + protected void validateConfiguration() {} + + public SeedStreamingClient build() { + validateConfiguration(); + return new SeedStreamingClient(buildClientOptions()); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ClientOptions.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ClientOptions.java new file mode 100644 index 000000000000..b9706dcaa396 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ClientOptions.java @@ -0,0 +1,221 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; +import okhttp3.OkHttpClient; + +public final class ClientOptions { + private final Environment environment; + + private final Map headers; + + private final Map> headerSuppliers; + + private final OkHttpClient httpClient; + + private final int timeout; + + private final int maxRetries; + + private final Optional logging; + + private ClientOptions( + Environment environment, + Map headers, + Map> headerSuppliers, + OkHttpClient httpClient, + int timeout, + int maxRetries, + Optional logging) { + this.environment = environment; + this.headers = new HashMap<>(); + this.headers.putAll(headers); + this.headers.putAll(new HashMap() { + { + put("User-Agent", "com.fern:streaming-parameter/0.0.1"); + put("X-Fern-Language", "JAVA"); + put("X-Fern-SDK-Name", "com.seed.fern:streaming-sdk"); + } + }); + this.headerSuppliers = headerSuppliers; + this.httpClient = httpClient; + this.timeout = timeout; + this.maxRetries = maxRetries; + this.logging = logging; + } + + public Environment environment() { + return this.environment; + } + + public Map headers(RequestOptions requestOptions) { + Map values = new HashMap<>(this.headers); + headerSuppliers.forEach((key, supplier) -> { + values.put(key, supplier.get()); + }); + if (requestOptions != null) { + values.putAll(requestOptions.getHeaders()); + } + return values; + } + + public int timeout(RequestOptions requestOptions) { + if (requestOptions == null) { + return this.timeout; + } + return requestOptions.getTimeout().orElse(this.timeout); + } + + public OkHttpClient httpClient() { + return this.httpClient; + } + + public OkHttpClient httpClientWithTimeout(RequestOptions requestOptions) { + if (requestOptions == null) { + return this.httpClient; + } + return this.httpClient + .newBuilder() + .callTimeout(requestOptions.getTimeout().get(), requestOptions.getTimeoutTimeUnit()) + .connectTimeout(0, TimeUnit.SECONDS) + .writeTimeout(0, TimeUnit.SECONDS) + .readTimeout(0, TimeUnit.SECONDS) + .build(); + } + + public int maxRetries() { + return this.maxRetries; + } + + public Optional logging() { + return this.logging; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private Environment environment; + + private final Map headers = new HashMap<>(); + + private final Map> headerSuppliers = new HashMap<>(); + + private int maxRetries = 2; + + private Optional timeout = Optional.empty(); + + private OkHttpClient httpClient = null; + + private Optional logging = Optional.empty(); + + public Builder environment(Environment environment) { + this.environment = environment; + return this; + } + + public Builder addHeader(String key, String value) { + this.headers.put(key, value); + return this; + } + + public Builder addHeader(String key, Supplier value) { + this.headerSuppliers.put(key, value); + return this; + } + + /** + * Override the timeout in seconds. Defaults to 60 seconds. + */ + public Builder timeout(int timeout) { + this.timeout = Optional.of(timeout); + return this; + } + + /** + * Override the timeout in seconds. Defaults to 60 seconds. + */ + public Builder timeout(Optional timeout) { + this.timeout = timeout; + return this; + } + + /** + * Override the maximum number of retries. Defaults to 2 retries. + */ + public Builder maxRetries(int maxRetries) { + this.maxRetries = maxRetries; + return this; + } + + public Builder httpClient(OkHttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Configure logging for the SDK. Silent by default — no log output unless explicitly configured. + */ + public Builder logging(LogConfig logging) { + this.logging = Optional.of(logging); + return this; + } + + public ClientOptions build() { + OkHttpClient.Builder httpClientBuilder = + this.httpClient != null ? this.httpClient.newBuilder() : new OkHttpClient.Builder(); + + if (this.httpClient != null) { + timeout.ifPresent(timeout -> httpClientBuilder + .callTimeout(timeout, TimeUnit.SECONDS) + .connectTimeout(0, TimeUnit.SECONDS) + .writeTimeout(0, TimeUnit.SECONDS) + .readTimeout(0, TimeUnit.SECONDS)); + } else { + httpClientBuilder + .callTimeout(this.timeout.orElse(60), TimeUnit.SECONDS) + .connectTimeout(0, TimeUnit.SECONDS) + .writeTimeout(0, TimeUnit.SECONDS) + .readTimeout(0, TimeUnit.SECONDS) + .addInterceptor(new RetryInterceptor(this.maxRetries)); + } + + Logger logger = Logger.from(this.logging); + httpClientBuilder.addInterceptor(new LoggingInterceptor(logger)); + + this.httpClient = httpClientBuilder.build(); + this.timeout = Optional.of(httpClient.callTimeoutMillis() / 1000); + + return new ClientOptions( + environment, + headers, + headerSuppliers, + httpClient, + this.timeout.get(), + this.maxRetries, + this.logging); + } + + /** + * Create a new Builder initialized with values from an existing ClientOptions + */ + public static Builder from(ClientOptions clientOptions) { + Builder builder = new Builder(); + builder.environment = clientOptions.environment(); + builder.timeout = Optional.of(clientOptions.timeout(null)); + builder.httpClient = clientOptions.httpClient(); + builder.headers.putAll(clientOptions.headers); + builder.headerSuppliers.putAll(clientOptions.headerSuppliers); + builder.maxRetries = clientOptions.maxRetries(); + builder.logging = clientOptions.logging(); + return builder; + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ConsoleLogger.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ConsoleLogger.java new file mode 100644 index 000000000000..121e30e2267a --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ConsoleLogger.java @@ -0,0 +1,51 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.util.logging.Level; + +/** + * Default logger implementation that writes to the console using {@link java.util.logging.Logger}. + * + *

Uses the "fern" logger name with a simple format of "LEVEL - message". + */ +public final class ConsoleLogger implements ILogger { + + private static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("fern"); + + static { + if (logger.getHandlers().length == 0) { + java.util.logging.ConsoleHandler handler = new java.util.logging.ConsoleHandler(); + handler.setFormatter(new java.util.logging.SimpleFormatter() { + @Override + public String format(java.util.logging.LogRecord record) { + return record.getLevel() + " - " + record.getMessage() + System.lineSeparator(); + } + }); + logger.addHandler(handler); + logger.setUseParentHandlers(false); + logger.setLevel(Level.ALL); + } + } + + @Override + public void debug(String message) { + logger.log(Level.FINE, message); + } + + @Override + public void info(String message) { + logger.log(Level.INFO, message); + } + + @Override + public void warn(String message) { + logger.log(Level.WARNING, message); + } + + @Override + public void error(String message) { + logger.log(Level.SEVERE, message); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/DateTimeDeserializer.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/DateTimeDeserializer.java new file mode 100644 index 000000000000..d34a0dbf8b94 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/DateTimeDeserializer.java @@ -0,0 +1,63 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.module.SimpleModule; +import java.io.IOException; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalQueries; + +/** + * Custom deserializer that handles converting ISO8601 dates into {@link OffsetDateTime} objects. + */ +class DateTimeDeserializer extends JsonDeserializer { + private static final SimpleModule MODULE; + + static { + MODULE = new SimpleModule().addDeserializer(OffsetDateTime.class, new DateTimeDeserializer()); + } + + /** + * Gets a module wrapping this deserializer as an adapter for the Jackson ObjectMapper. + * + * @return A {@link SimpleModule} to be plugged onto Jackson ObjectMapper. + */ + public static SimpleModule getModule() { + return MODULE; + } + + @Override + public OffsetDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException { + JsonToken token = parser.currentToken(); + if (token == JsonToken.VALUE_NUMBER_INT) { + return OffsetDateTime.ofInstant(Instant.ofEpochSecond(parser.getValueAsLong()), ZoneOffset.UTC); + } else { + String value = parser.getValueAsString(); + TemporalAccessor temporal; + try { + temporal = DateTimeFormatter.ISO_DATE_TIME.parseBest(value, OffsetDateTime::from, LocalDateTime::from); + } catch (DateTimeParseException e) { + // Fall back to space-separated format (e.g. "2025-02-15 10:30:00+00:00"). + temporal = DateTimeFormatter.ISO_DATE_TIME.parseBest( + value.replace(' ', 'T'), OffsetDateTime::from, LocalDateTime::from); + } + + if (temporal.query(TemporalQueries.offset()) == null) { + return LocalDateTime.from(temporal).atOffset(ZoneOffset.UTC); + } else { + return OffsetDateTime.from(temporal); + } + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/DoubleSerializer.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/DoubleSerializer.java new file mode 100644 index 000000000000..5bd7ae5fdd24 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/DoubleSerializer.java @@ -0,0 +1,43 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleModule; +import java.io.IOException; + +/** + * Custom serializer that writes integer-valued doubles without a decimal point. + * For example, {@code 24000.0} is serialized as {@code 24000} instead of {@code 24000.0}. + * Non-integer values like {@code 3.14} are serialized normally. + */ +class DoubleSerializer extends JsonSerializer { + private static final SimpleModule MODULE; + + static { + MODULE = new SimpleModule() + .addSerializer(Double.class, new DoubleSerializer()) + .addSerializer(double.class, new DoubleSerializer()); + } + + /** + * Gets a module wrapping this serializer as an adapter for the Jackson ObjectMapper. + * + * @return A {@link SimpleModule} to be plugged onto Jackson ObjectMapper. + */ + public static SimpleModule getModule() { + return MODULE; + } + + @Override + public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + if (value != null && value == Math.floor(value) && !Double.isInfinite(value) && !Double.isNaN(value)) { + gen.writeNumber(value.longValue()); + } else { + gen.writeNumber(value); + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Environment.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Environment.java new file mode 100644 index 000000000000..563f1fc09bd3 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Environment.java @@ -0,0 +1,20 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +public final class Environment { + private final String url; + + private Environment(String url) { + this.url = url; + } + + public String getUrl() { + return this.url; + } + + public static Environment custom(String url) { + return new Environment(url); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/FileStream.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/FileStream.java new file mode 100644 index 000000000000..4173800f0cea --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/FileStream.java @@ -0,0 +1,60 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.io.InputStream; +import java.util.Objects; +import okhttp3.MediaType; +import okhttp3.RequestBody; +import org.jetbrains.annotations.Nullable; + +/** + * Represents a file stream with associated metadata for file uploads. + */ +public class FileStream { + private final InputStream inputStream; + private final String fileName; + private final MediaType contentType; + + /** + * Constructs a FileStream with the given input stream and optional metadata. + * + * @param inputStream The input stream of the file content. Must not be null. + * @param fileName The name of the file, or null if unknown. + * @param contentType The MIME type of the file content, or null if unknown. + * @throws NullPointerException if inputStream is null + */ + public FileStream(InputStream inputStream, @Nullable String fileName, @Nullable MediaType contentType) { + this.inputStream = Objects.requireNonNull(inputStream, "Input stream cannot be null"); + this.fileName = fileName; + this.contentType = contentType; + } + + public FileStream(InputStream inputStream) { + this(inputStream, null, null); + } + + public InputStream getInputStream() { + return inputStream; + } + + @Nullable + public String getFileName() { + return fileName; + } + + @Nullable + public MediaType getContentType() { + return contentType; + } + + /** + * Creates a RequestBody suitable for use with OkHttp client. + * + * @return A RequestBody instance representing this file stream. + */ + public RequestBody toRequestBody() { + return new InputStreamRequestBody(contentType, inputStream); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ILogger.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ILogger.java new file mode 100644 index 000000000000..66d5d54d791f --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ILogger.java @@ -0,0 +1,38 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +/** + * Interface for custom logger implementations. + * + *

Implement this interface to provide a custom logging backend for the SDK. + * The SDK will call the appropriate method based on the log level. + * + *

Example: + *

{@code
+ * public class MyCustomLogger implements ILogger {
+ *     public void debug(String message) {
+ *         System.out.println("[DBG] " + message);
+ *     }
+ *     public void info(String message) {
+ *         System.out.println("[INF] " + message);
+ *     }
+ *     public void warn(String message) {
+ *         System.out.println("[WRN] " + message);
+ *     }
+ *     public void error(String message) {
+ *         System.out.println("[ERR] " + message);
+ *     }
+ * }
+ * }
+ */ +public interface ILogger { + void debug(String message); + + void info(String message); + + void warn(String message); + + void error(String message); +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/InputStreamRequestBody.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/InputStreamRequestBody.java new file mode 100644 index 000000000000..15f963ac5dc0 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/InputStreamRequestBody.java @@ -0,0 +1,74 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Objects; +import okhttp3.MediaType; +import okhttp3.RequestBody; +import okio.BufferedSink; +import okio.Okio; +import okio.Source; +import org.jetbrains.annotations.Nullable; + +/** + * A custom implementation of OkHttp's RequestBody that wraps an InputStream. + * This class allows streaming of data from an InputStream directly to an HTTP request body, + * which is useful for file uploads or sending large amounts of data without loading it all into memory. + */ +public class InputStreamRequestBody extends RequestBody { + private final InputStream inputStream; + private final MediaType contentType; + + /** + * Constructs an InputStreamRequestBody with the specified content type and input stream. + * + * @param contentType the MediaType of the content, or null if not known + * @param inputStream the InputStream containing the data to be sent + * @throws NullPointerException if inputStream is null + */ + public InputStreamRequestBody(@Nullable MediaType contentType, InputStream inputStream) { + this.contentType = contentType; + this.inputStream = Objects.requireNonNull(inputStream, "inputStream == null"); + } + + /** + * Returns the content type of this request body. + * + * @return the MediaType of the content, or null if not specified + */ + @Nullable + @Override + public MediaType contentType() { + return contentType; + } + + /** + * Returns the content length of this request body, if known. + * This method attempts to determine the length using the InputStream's available() method, + * which may not always accurately reflect the total length of the stream. + * + * @return the content length, or -1 if the length is unknown + * @throws IOException if an I/O error occurs + */ + @Override + public long contentLength() throws IOException { + return inputStream.available() == 0 ? -1 : inputStream.available(); + } + + /** + * Writes the content of the InputStream to the given BufferedSink. + * This method is responsible for transferring the data from the InputStream to the network request. + * + * @param sink the BufferedSink to write the content to + * @throws IOException if an I/O error occurs during writing + */ + @Override + public void writeTo(BufferedSink sink) throws IOException { + try (Source source = Okio.source(inputStream)) { + sink.writeAll(source); + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/LogConfig.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/LogConfig.java new file mode 100644 index 000000000000..8153e9177c86 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/LogConfig.java @@ -0,0 +1,98 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +/** + * Configuration for SDK logging. + * + *

Use the builder to configure logging behavior: + *

{@code
+ * LogConfig config = LogConfig.builder()
+ *     .level(LogLevel.DEBUG)
+ *     .silent(false)
+ *     .build();
+ * }
+ * + *

Or with a custom logger: + *

{@code
+ * LogConfig config = LogConfig.builder()
+ *     .level(LogLevel.DEBUG)
+ *     .logger(new MyCustomLogger())
+ *     .silent(false)
+ *     .build();
+ * }
+ * + *

Defaults: + *

    + *
  • {@code level} — {@link LogLevel#INFO}
  • + *
  • {@code logger} — {@link ConsoleLogger} (writes to stderr via java.util.logging)
  • + *
  • {@code silent} — {@code true} (no output unless explicitly enabled)
  • + *
+ */ +public final class LogConfig { + + private final LogLevel level; + private final ILogger logger; + private final boolean silent; + + private LogConfig(LogLevel level, ILogger logger, boolean silent) { + this.level = level; + this.logger = logger; + this.silent = silent; + } + + public LogLevel level() { + return level; + } + + public ILogger logger() { + return logger; + } + + public boolean silent() { + return silent; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private LogLevel level = LogLevel.INFO; + private ILogger logger = new ConsoleLogger(); + private boolean silent = true; + + private Builder() {} + + /** + * Set the minimum log level. Only messages at this level or above will be logged. + * Defaults to {@link LogLevel#INFO}. + */ + public Builder level(LogLevel level) { + this.level = level; + return this; + } + + /** + * Set a custom logger implementation. Defaults to {@link ConsoleLogger}. + */ + public Builder logger(ILogger logger) { + this.logger = logger; + return this; + } + + /** + * Set whether logging is silent (disabled). Defaults to {@code true}. + * Set to {@code false} to enable log output. + */ + public Builder silent(boolean silent) { + this.silent = silent; + return this; + } + + public LogConfig build() { + return new LogConfig(level, logger, silent); + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/LogLevel.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/LogLevel.java new file mode 100644 index 000000000000..898412f15e53 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/LogLevel.java @@ -0,0 +1,36 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +/** + * Log levels for SDK logging configuration. + * Silent by default — no log output unless explicitly configured. + */ +public enum LogLevel { + DEBUG(1), + INFO(2), + WARN(3), + ERROR(4); + + private final int value; + + LogLevel(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + /** + * Parse a log level from a string (case-insensitive). + * + * @param level the level string (debug, info, warn, error) + * @return the corresponding LogLevel + * @throws IllegalArgumentException if the string does not match any level + */ + public static LogLevel fromString(String level) { + return LogLevel.valueOf(level.toUpperCase()); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Logger.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Logger.java new file mode 100644 index 000000000000..1d2c188abed6 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Logger.java @@ -0,0 +1,97 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +/** + * SDK logger that filters messages based on level and silent mode. + * + *

Silent by default — no log output unless explicitly configured. + * Create via {@link LogConfig} or directly: + *

{@code
+ * Logger logger = new Logger(LogLevel.DEBUG, new ConsoleLogger(), false);
+ * logger.debug("request sent");
+ * }
+ */ +public final class Logger { + + private static final Logger DEFAULT = new Logger(LogLevel.INFO, new ConsoleLogger(), true); + + private final LogLevel level; + private final ILogger logger; + private final boolean silent; + + public Logger(LogLevel level, ILogger logger, boolean silent) { + this.level = level; + this.logger = logger; + this.silent = silent; + } + + /** + * Returns a default silent logger (no output). + */ + public static Logger getDefault() { + return DEFAULT; + } + + /** + * Creates a Logger from a {@link LogConfig}. If config is {@code null}, returns the default silent logger. + */ + public static Logger from(LogConfig config) { + if (config == null) { + return DEFAULT; + } + return new Logger(config.level(), config.logger(), config.silent()); + } + + /** + * Creates a Logger from an {@code Optional}. If empty, returns the default silent logger. + */ + public static Logger from(java.util.Optional config) { + return config.map(Logger::from).orElse(DEFAULT); + } + + private boolean shouldLog(LogLevel messageLevel) { + return !silent && level.getValue() <= messageLevel.getValue(); + } + + public boolean isDebug() { + return shouldLog(LogLevel.DEBUG); + } + + public boolean isInfo() { + return shouldLog(LogLevel.INFO); + } + + public boolean isWarn() { + return shouldLog(LogLevel.WARN); + } + + public boolean isError() { + return shouldLog(LogLevel.ERROR); + } + + public void debug(String message) { + if (isDebug()) { + logger.debug(message); + } + } + + public void info(String message) { + if (isInfo()) { + logger.info(message); + } + } + + public void warn(String message) { + if (isWarn()) { + logger.warn(message); + } + } + + public void error(String message) { + if (isError()) { + logger.error(message); + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/LoggingInterceptor.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/LoggingInterceptor.java new file mode 100644 index 000000000000..e26de62d78c4 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/LoggingInterceptor.java @@ -0,0 +1,104 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +/** + * OkHttp interceptor that logs HTTP requests and responses. + * + *

Logs request method, URL, and headers (with sensitive values redacted) at debug level. + * Logs response status at debug level, and 4xx/5xx responses at error level. + * Does nothing if the logger is silent. + */ +public final class LoggingInterceptor implements Interceptor { + + private static final Set SENSITIVE_HEADERS = new HashSet<>(Arrays.asList( + "authorization", + "www-authenticate", + "x-api-key", + "api-key", + "apikey", + "x-api-token", + "x-auth-token", + "auth-token", + "proxy-authenticate", + "proxy-authorization", + "cookie", + "set-cookie", + "x-csrf-token", + "x-xsrf-token", + "x-session-token", + "x-access-token")); + + private final Logger logger; + + public LoggingInterceptor(Logger logger) { + this.logger = logger; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + if (logger.isDebug()) { + StringBuilder sb = new StringBuilder(); + sb.append("HTTP Request: ").append(request.method()).append(" ").append(request.url()); + sb.append(" headers={"); + boolean first = true; + for (String name : request.headers().names()) { + if (!first) { + sb.append(", "); + } + sb.append(name).append("="); + if (SENSITIVE_HEADERS.contains(name.toLowerCase())) { + sb.append("[REDACTED]"); + } else { + sb.append(request.header(name)); + } + first = false; + } + sb.append("}"); + sb.append(" has_body=").append(request.body() != null); + logger.debug(sb.toString()); + } + + Response response = chain.proceed(request); + + if (logger.isDebug()) { + StringBuilder sb = new StringBuilder(); + sb.append("HTTP Response: status=").append(response.code()); + sb.append(" url=").append(response.request().url()); + sb.append(" headers={"); + boolean first = true; + for (String name : response.headers().names()) { + if (!first) { + sb.append(", "); + } + sb.append(name).append("="); + if (SENSITIVE_HEADERS.contains(name.toLowerCase())) { + sb.append("[REDACTED]"); + } else { + sb.append(response.header(name)); + } + first = false; + } + sb.append("}"); + logger.debug(sb.toString()); + } + + if (response.code() >= 400 && logger.isError()) { + logger.error("HTTP Error: status=" + response.code() + " url=" + + response.request().url()); + } + + return response; + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/MediaTypes.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/MediaTypes.java new file mode 100644 index 000000000000..24a9a00e6072 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/MediaTypes.java @@ -0,0 +1,13 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import okhttp3.MediaType; + +public final class MediaTypes { + + public static final MediaType APPLICATION_JSON = MediaType.parse("application/json"); + + private MediaTypes() {} +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Nullable.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Nullable.java new file mode 100644 index 000000000000..022175d4145b --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Nullable.java @@ -0,0 +1,140 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.util.Optional; +import java.util.function.Function; + +public final class Nullable { + + private final Either, Null> value; + + private Nullable() { + this.value = Either.left(Optional.empty()); + } + + private Nullable(T value) { + if (value == null) { + this.value = Either.right(Null.INSTANCE); + } else { + this.value = Either.left(Optional.of(value)); + } + } + + public static Nullable ofNull() { + return new Nullable<>(null); + } + + public static Nullable of(T value) { + return new Nullable<>(value); + } + + public static Nullable empty() { + return new Nullable<>(); + } + + public static Nullable ofOptional(Optional value) { + if (value.isPresent()) { + return of(value.get()); + } else { + return empty(); + } + } + + public boolean isNull() { + return this.value.isRight(); + } + + public boolean isEmpty() { + return this.value.isLeft() && !this.value.getLeft().isPresent(); + } + + public T get() { + if (this.isNull()) { + return null; + } + + return this.value.getLeft().get(); + } + + public Nullable map(Function mapper) { + if (this.isNull()) { + return Nullable.ofNull(); + } + + return Nullable.ofOptional(this.value.getLeft().map(mapper)); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof Nullable)) { + return false; + } + + if (((Nullable) other).isNull() && this.isNull()) { + return true; + } + + return this.value.getLeft().equals(((Nullable) other).value.getLeft()); + } + + private static final class Either { + private L left = null; + private R right = null; + + private Either(L left, R right) { + if (left != null && right != null) { + throw new IllegalArgumentException("Left and right argument cannot both be non-null."); + } + + if (left == null && right == null) { + throw new IllegalArgumentException("Left and right argument cannot both be null."); + } + + if (left != null) { + this.left = left; + } + + if (right != null) { + this.right = right; + } + } + + public static Either left(L left) { + return new Either<>(left, null); + } + + public static Either right(R right) { + return new Either<>(null, right); + } + + public boolean isLeft() { + return this.left != null; + } + + public boolean isRight() { + return this.right != null; + } + + public L getLeft() { + if (!this.isLeft()) { + throw new IllegalArgumentException("Cannot get left from right Either."); + } + return this.left; + } + + public R getRight() { + if (!this.isRight()) { + throw new IllegalArgumentException("Cannot get right from left Either."); + } + return this.right; + } + } + + private static final class Null { + private static final Null INSTANCE = new Null(); + + private Null() {} + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/NullableNonemptyFilter.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/NullableNonemptyFilter.java new file mode 100644 index 000000000000..3a7b65e956e2 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/NullableNonemptyFilter.java @@ -0,0 +1,22 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.util.Optional; + +public final class NullableNonemptyFilter { + @Override + public boolean equals(Object o) { + boolean isOptionalEmpty = isOptionalEmpty(o); + + return isOptionalEmpty; + } + + private boolean isOptionalEmpty(Object o) { + if (o instanceof Optional) { + return !((Optional) o).isPresent(); + } + return false; + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ObjectMappers.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ObjectMappers.java new file mode 100644 index 000000000000..2583c0195d04 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ObjectMappers.java @@ -0,0 +1,46 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.io.IOException; + +public final class ObjectMappers { + public static final ObjectMapper JSON_MAPPER = JsonMapper.builder() + .addModule(new Jdk8Module()) + .addModule(new JavaTimeModule()) + .addModule(DateTimeDeserializer.getModule()) + .addModule(DoubleSerializer.getModule()) + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .build(); + + private ObjectMappers() {} + + public static String stringify(Object o) { + try { + return JSON_MAPPER + .setSerializationInclusion(JsonInclude.Include.ALWAYS) + .writerWithDefaultPrettyPrinter() + .writeValueAsString(o); + } catch (IOException e) { + return o.getClass().getName() + "@" + Integer.toHexString(o.hashCode()); + } + } + + public static Object parseErrorBody(String responseBodyString) { + try { + return JSON_MAPPER.readValue(responseBodyString, Object.class); + } catch (JsonProcessingException ignored) { + return responseBodyString; + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/QueryStringMapper.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/QueryStringMapper.java new file mode 100644 index 000000000000..5b2a7bdf4949 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/QueryStringMapper.java @@ -0,0 +1,142 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import okhttp3.HttpUrl; +import okhttp3.MultipartBody; + +public class QueryStringMapper { + + private static final ObjectMapper MAPPER = ObjectMappers.JSON_MAPPER; + + public static void addQueryParameter(HttpUrl.Builder httpUrl, String key, Object value, boolean arraysAsRepeats) { + JsonNode valueNode = MAPPER.valueToTree(value); + + List> flat; + if (valueNode.isObject()) { + flat = flattenObject((ObjectNode) valueNode, arraysAsRepeats); + } else if (valueNode.isArray()) { + flat = flattenArray((ArrayNode) valueNode, "", arraysAsRepeats); + } else { + if (valueNode.isTextual()) { + httpUrl.addQueryParameter(key, valueNode.textValue()); + } else { + httpUrl.addQueryParameter(key, valueNode.toString()); + } + return; + } + + for (Map.Entry field : flat) { + if (field.getValue().isTextual()) { + httpUrl.addQueryParameter(key + field.getKey(), field.getValue().textValue()); + } else { + httpUrl.addQueryParameter(key + field.getKey(), field.getValue().toString()); + } + } + } + + public static void addFormDataPart( + MultipartBody.Builder multipartBody, String key, Object value, boolean arraysAsRepeats) { + JsonNode valueNode = MAPPER.valueToTree(value); + + List> flat; + if (valueNode.isObject()) { + flat = flattenObject((ObjectNode) valueNode, arraysAsRepeats); + } else if (valueNode.isArray()) { + flat = flattenArray((ArrayNode) valueNode, "", arraysAsRepeats); + } else { + if (valueNode.isTextual()) { + multipartBody.addFormDataPart(key, valueNode.textValue()); + } else { + multipartBody.addFormDataPart(key, valueNode.toString()); + } + return; + } + + for (Map.Entry field : flat) { + if (field.getValue().isTextual()) { + multipartBody.addFormDataPart( + key + field.getKey(), field.getValue().textValue()); + } else { + multipartBody.addFormDataPart( + key + field.getKey(), field.getValue().toString()); + } + } + } + + public static List> flattenObject(ObjectNode object, boolean arraysAsRepeats) { + List> flat = new ArrayList<>(); + + Iterator> fields = object.fields(); + while (fields.hasNext()) { + Map.Entry field = fields.next(); + + String key = "[" + field.getKey() + "]"; + + if (field.getValue().isObject()) { + List> flatField = + flattenObject((ObjectNode) field.getValue(), arraysAsRepeats); + addAll(flat, flatField, key); + } else if (field.getValue().isArray()) { + List> flatField = + flattenArray((ArrayNode) field.getValue(), key, arraysAsRepeats); + addAll(flat, flatField, ""); + } else { + flat.add(new AbstractMap.SimpleEntry<>(key, field.getValue())); + } + } + + return flat; + } + + private static List> flattenArray( + ArrayNode array, String key, boolean arraysAsRepeats) { + List> flat = new ArrayList<>(); + + Iterator elements = array.elements(); + + int index = 0; + while (elements.hasNext()) { + JsonNode element = elements.next(); + + String indexKey = key + "[" + index + "]"; + + if (arraysAsRepeats) { + indexKey = key; + } + + if (element.isObject()) { + List> flatField = flattenObject((ObjectNode) element, arraysAsRepeats); + addAll(flat, flatField, indexKey); + } else if (element.isArray()) { + List> flatField = flattenArray((ArrayNode) element, "", arraysAsRepeats); + addAll(flat, flatField, indexKey); + } else { + flat.add(new AbstractMap.SimpleEntry<>(indexKey, element)); + } + + index++; + } + + return flat; + } + + private static void addAll( + List> target, List> source, String prefix) { + for (Map.Entry entry : source) { + Map.Entry entryToAdd = + new AbstractMap.SimpleEntry<>(prefix + entry.getKey(), entry.getValue()); + target.add(entryToAdd); + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/RequestOptions.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/RequestOptions.java new file mode 100644 index 000000000000..e310fe46e16e --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/RequestOptions.java @@ -0,0 +1,118 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +public final class RequestOptions { + private final Optional timeout; + + private final TimeUnit timeoutTimeUnit; + + private final Map headers; + + private final Map> headerSuppliers; + + private final Map queryParameters; + + private final Map> queryParameterSuppliers; + + private RequestOptions( + Optional timeout, + TimeUnit timeoutTimeUnit, + Map headers, + Map> headerSuppliers, + Map queryParameters, + Map> queryParameterSuppliers) { + this.timeout = timeout; + this.timeoutTimeUnit = timeoutTimeUnit; + this.headers = headers; + this.headerSuppliers = headerSuppliers; + this.queryParameters = queryParameters; + this.queryParameterSuppliers = queryParameterSuppliers; + } + + public Optional getTimeout() { + return timeout; + } + + public TimeUnit getTimeoutTimeUnit() { + return timeoutTimeUnit; + } + + public Map getHeaders() { + Map headers = new HashMap<>(); + headers.putAll(this.headers); + this.headerSuppliers.forEach((key, supplier) -> { + headers.put(key, supplier.get()); + }); + return headers; + } + + public Map getQueryParameters() { + Map queryParameters = new HashMap<>(this.queryParameters); + this.queryParameterSuppliers.forEach((key, supplier) -> { + queryParameters.put(key, supplier.get()); + }); + return queryParameters; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private Optional timeout = Optional.empty(); + + private TimeUnit timeoutTimeUnit = TimeUnit.SECONDS; + + private final Map headers = new HashMap<>(); + + private final Map> headerSuppliers = new HashMap<>(); + + private final Map queryParameters = new HashMap<>(); + + private final Map> queryParameterSuppliers = new HashMap<>(); + + public Builder timeout(Integer timeout) { + this.timeout = Optional.of(timeout); + return this; + } + + public Builder timeout(Integer timeout, TimeUnit timeoutTimeUnit) { + this.timeout = Optional.of(timeout); + this.timeoutTimeUnit = timeoutTimeUnit; + return this; + } + + public Builder addHeader(String key, String value) { + this.headers.put(key, value); + return this; + } + + public Builder addHeader(String key, Supplier value) { + this.headerSuppliers.put(key, value); + return this; + } + + public Builder addQueryParameter(String key, String value) { + this.queryParameters.put(key, value); + return this; + } + + public Builder addQueryParameter(String key, Supplier value) { + this.queryParameterSuppliers.put(key, value); + return this; + } + + public RequestOptions build() { + return new RequestOptions( + timeout, timeoutTimeUnit, headers, headerSuppliers, queryParameters, queryParameterSuppliers); + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ResponseBodyInputStream.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ResponseBodyInputStream.java new file mode 100644 index 000000000000..eac0f9a6aef9 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ResponseBodyInputStream.java @@ -0,0 +1,45 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.io.FilterInputStream; +import java.io.IOException; +import okhttp3.Response; + +/** + * A custom InputStream that wraps the InputStream from the OkHttp Response and ensures that the + * OkHttp Response object is properly closed when the stream is closed. + * + * This class extends FilterInputStream and takes an OkHttp Response object as a parameter. + * It retrieves the InputStream from the Response and overrides the close method to close + * both the InputStream and the Response object, ensuring proper resource management and preventing + * premature closure of the underlying HTTP connection. + */ +public class ResponseBodyInputStream extends FilterInputStream { + private final Response response; + + /** + * Constructs a ResponseBodyInputStream that wraps the InputStream from the given OkHttp + * Response object. + * + * @param response the OkHttp Response object from which the InputStream is retrieved + * @throws IOException if an I/O error occurs while retrieving the InputStream + */ + public ResponseBodyInputStream(Response response) throws IOException { + super(response.body().byteStream()); + this.response = response; + } + + /** + * Closes the InputStream and the associated OkHttp Response object. This ensures that the + * underlying HTTP connection is properly closed after the stream is no longer needed. + * + * @throws IOException if an I/O error occurs + */ + @Override + public void close() throws IOException { + super.close(); + response.close(); // Ensure the response is closed when the stream is closed + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ResponseBodyReader.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ResponseBodyReader.java new file mode 100644 index 000000000000..e3fbc8e5958e --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/ResponseBodyReader.java @@ -0,0 +1,44 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.io.FilterReader; +import java.io.IOException; +import okhttp3.Response; + +/** + * A custom Reader that wraps the Reader from the OkHttp Response and ensures that the + * OkHttp Response object is properly closed when the reader is closed. + * + * This class extends FilterReader and takes an OkHttp Response object as a parameter. + * It retrieves the Reader from the Response and overrides the close method to close + * both the Reader and the Response object, ensuring proper resource management and preventing + * premature closure of the underlying HTTP connection. + */ +public class ResponseBodyReader extends FilterReader { + private final Response response; + + /** + * Constructs a ResponseBodyReader that wraps the Reader from the given OkHttp Response object. + * + * @param response the OkHttp Response object from which the Reader is retrieved + * @throws IOException if an I/O error occurs while retrieving the Reader + */ + public ResponseBodyReader(Response response) throws IOException { + super(response.body().charStream()); + this.response = response; + } + + /** + * Closes the Reader and the associated OkHttp Response object. This ensures that the + * underlying HTTP connection is properly closed after the reader is no longer needed. + * + * @throws IOException if an I/O error occurs + */ + @Override + public void close() throws IOException { + super.close(); + response.close(); // Ensure the response is closed when the reader is closed + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/RetryInterceptor.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/RetryInterceptor.java new file mode 100644 index 000000000000..87637c55738d --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/RetryInterceptor.java @@ -0,0 +1,181 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.io.IOException; +import java.time.Duration; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Optional; +import java.util.Random; +import okhttp3.Interceptor; +import okhttp3.Response; + +public class RetryInterceptor implements Interceptor { + + private static final Duration INITIAL_RETRY_DELAY = Duration.ofMillis(1000); + private static final Duration MAX_RETRY_DELAY = Duration.ofMillis(60000); + private static final double JITTER_FACTOR = 0.2; + + private final int maxRetries; + private final Random random = new Random(); + + public RetryInterceptor(int maxRetries) { + this.maxRetries = maxRetries; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Response response = chain.proceed(chain.request()); + + if (shouldRetry(response.code())) { + return retryChain(response, chain); + } + + return response; + } + + private Response retryChain(Response response, Chain chain) throws IOException { + ExponentialBackoff backoff = new ExponentialBackoff(this.maxRetries); + Optional nextBackoff = backoff.nextBackoff(response); + while (nextBackoff.isPresent()) { + try { + Thread.sleep(nextBackoff.get().toMillis()); + } catch (InterruptedException e) { + throw new IOException("Interrupted while trying request", e); + } + response.close(); + response = chain.proceed(chain.request()); + if (shouldRetry(response.code())) { + nextBackoff = backoff.nextBackoff(response); + } else { + return response; + } + } + + return response; + } + + /** + * Calculates the retry delay from response headers, with fallback to exponential backoff. + * Priority: Retry-After > X-RateLimit-Reset > Exponential Backoff + */ + private Duration getRetryDelayFromHeaders(Response response, int retryAttempt) { + // Check for Retry-After header first (RFC 7231), with no jitter + String retryAfter = response.header("Retry-After"); + if (retryAfter != null) { + // Parse as number of seconds... + Optional secondsDelay = tryParseLong(retryAfter) + .map(seconds -> seconds * 1000) + .filter(delayMs -> delayMs > 0) + .map(delayMs -> Math.min(delayMs, MAX_RETRY_DELAY.toMillis())) + .map(Duration::ofMillis); + if (secondsDelay.isPresent()) { + return secondsDelay.get(); + } + + // ...or as an HTTP date; both are valid + Optional dateDelay = tryParseHttpDate(retryAfter) + .map(resetTime -> resetTime.toInstant().toEpochMilli() - System.currentTimeMillis()) + .filter(delayMs -> delayMs > 0) + .map(delayMs -> Math.min(delayMs, MAX_RETRY_DELAY.toMillis())) + .map(Duration::ofMillis); + if (dateDelay.isPresent()) { + return dateDelay.get(); + } + } + + // Then check for industry-standard X-RateLimit-Reset header, with positive jitter + String rateLimitReset = response.header("X-RateLimit-Reset"); + if (rateLimitReset != null) { + // Assume Unix timestamp in epoch seconds + Optional rateLimitDelay = tryParseLong(rateLimitReset) + .map(resetTimeSeconds -> (resetTimeSeconds * 1000) - System.currentTimeMillis()) + .filter(delayMs -> delayMs > 0) + .map(delayMs -> Math.min(delayMs, MAX_RETRY_DELAY.toMillis())) + .map(this::addPositiveJitter) + .map(Duration::ofMillis); + if (rateLimitDelay.isPresent()) { + return rateLimitDelay.get(); + } + } + + // Fall back to exponential backoff, with symmetric jitter + long baseDelay = INITIAL_RETRY_DELAY.toMillis() * (1L << retryAttempt); // 2^retryAttempt + long cappedDelay = Math.min(baseDelay, MAX_RETRY_DELAY.toMillis()); + return Duration.ofMillis(addSymmetricJitter(cappedDelay)); + } + + /** + * Attempts to parse a string as a long, returning empty Optional on failure. + */ + private Optional tryParseLong(String value) { + if (value == null) { + return Optional.empty(); + } + try { + return Optional.of(Long.parseLong(value)); + } catch (NumberFormatException e) { + return Optional.empty(); + } + } + + /** + * Attempts to parse a string as an HTTP date (RFC 1123), returning empty Optional on failure. + */ + private Optional tryParseHttpDate(String value) { + if (value == null) { + return Optional.empty(); + } + try { + return Optional.of(ZonedDateTime.parse(value, DateTimeFormatter.RFC_1123_DATE_TIME)); + } catch (DateTimeParseException e) { + return Optional.empty(); + } + } + + /** + * Adds positive jitter (100-120% of original value) to prevent thundering herd. + * Used for X-RateLimit-Reset header delays. + */ + private long addPositiveJitter(long delayMs) { + double jitterMultiplier = 1.0 + (random.nextDouble() * JITTER_FACTOR); + return (long) (delayMs * jitterMultiplier); + } + + /** + * Adds symmetric jitter (90-110% of original value) to prevent thundering herd. + * Used for exponential backoff delays. + */ + private long addSymmetricJitter(long delayMs) { + double jitterMultiplier = 1.0 + ((random.nextDouble() - 0.5) * JITTER_FACTOR); + return (long) (delayMs * jitterMultiplier); + } + + private static boolean shouldRetry(int statusCode) { + return statusCode == 408 || statusCode == 429 || statusCode >= 500; + } + + private final class ExponentialBackoff { + + private final int maxNumRetries; + + private int retryNumber = 0; + + ExponentialBackoff(int maxNumRetries) { + this.maxNumRetries = maxNumRetries; + } + + public Optional nextBackoff(Response response) { + if (retryNumber >= maxNumRetries) { + return Optional.empty(); + } + + Duration delay = getRetryDelayFromHeaders(response, retryNumber); + retryNumber += 1; + return Optional.of(delay); + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Rfc2822DateTimeDeserializer.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Rfc2822DateTimeDeserializer.java new file mode 100644 index 000000000000..3f05c05f7bd0 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Rfc2822DateTimeDeserializer.java @@ -0,0 +1,25 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import java.io.IOException; +import java.time.OffsetDateTime; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +/** + * Custom deserializer that handles converting RFC 2822 (RFC 1123) dates into {@link OffsetDateTime} objects. + * This is used for fields with format "date-time-rfc-2822", such as Twilio's dateCreated, dateSent, dateUpdated. + */ +public class Rfc2822DateTimeDeserializer extends JsonDeserializer { + + @Override + public OffsetDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException { + String raw = parser.getValueAsString(); + return ZonedDateTime.parse(raw, DateTimeFormatter.RFC_1123_DATE_TIME).toOffsetDateTime(); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SeedStreamingApiException.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SeedStreamingApiException.java new file mode 100644 index 000000000000..309f1931bcac --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SeedStreamingApiException.java @@ -0,0 +1,73 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import okhttp3.Response; + +/** + * This exception type will be thrown for any non-2XX API responses. + */ +public class SeedStreamingApiException extends SeedStreamingException { + /** + * The error code of the response that triggered the exception. + */ + private final int statusCode; + + /** + * The body of the response that triggered the exception. + */ + private final Object body; + + private final Map> headers; + + public SeedStreamingApiException(String message, int statusCode, Object body) { + super(message); + this.statusCode = statusCode; + this.body = body; + this.headers = new HashMap<>(); + } + + public SeedStreamingApiException(String message, int statusCode, Object body, Response rawResponse) { + super(message); + this.statusCode = statusCode; + this.body = body; + this.headers = new HashMap<>(); + rawResponse.headers().forEach(header -> { + String key = header.component1(); + String value = header.component2(); + this.headers.computeIfAbsent(key, _str -> new ArrayList<>()).add(value); + }); + } + + /** + * @return the statusCode + */ + public int statusCode() { + return this.statusCode; + } + + /** + * @return the body + */ + public Object body() { + return this.body; + } + + /** + * @return the headers + */ + public Map> headers() { + return this.headers; + } + + @Override + public String toString() { + return "SeedStreamingApiException{" + "message: " + getMessage() + ", statusCode: " + statusCode + ", body: " + + ObjectMappers.stringify(body) + "}"; + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SeedStreamingException.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SeedStreamingException.java new file mode 100644 index 000000000000..56212c0b5ad5 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SeedStreamingException.java @@ -0,0 +1,17 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +/** + * This class serves as the base exception for all errors in the SDK. + */ +public class SeedStreamingException extends RuntimeException { + public SeedStreamingException(String message) { + super(message); + } + + public SeedStreamingException(String message, Exception e) { + super(message, e); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SeedStreamingHttpResponse.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SeedStreamingHttpResponse.java new file mode 100644 index 000000000000..5a9803936760 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SeedStreamingHttpResponse.java @@ -0,0 +1,37 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import okhttp3.Response; + +public final class SeedStreamingHttpResponse { + + private final T body; + + private final Map> headers; + + public SeedStreamingHttpResponse(T body, Response rawResponse) { + this.body = body; + + Map> headers = new HashMap<>(); + rawResponse.headers().forEach(header -> { + String key = header.component1(); + String value = header.component2(); + headers.computeIfAbsent(key, _str -> new ArrayList<>()).add(value); + }); + this.headers = headers; + } + + public T body() { + return this.body; + } + + public Map> headers() { + return headers; + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SseEvent.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SseEvent.java new file mode 100644 index 000000000000..956bf00ce278 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SseEvent.java @@ -0,0 +1,114 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; +import java.util.Optional; + +/** + * Represents a Server-Sent Event with all standard fields. + * Used for event-level discrimination where the discriminator is at the SSE envelope level. + * + * @param The type of the data field + */ +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonIgnoreProperties(ignoreUnknown = true) +public final class SseEvent { + private final String event; + private final T data; + private final String id; + private final Long retry; + + private SseEvent(String event, T data, String id, Long retry) { + this.event = event; + this.data = data; + this.id = id; + this.retry = retry; + } + + @JsonProperty("event") + public Optional getEvent() { + return Optional.ofNullable(event); + } + + @JsonProperty("data") + public T getData() { + return data; + } + + @JsonProperty("id") + public Optional getId() { + return Optional.ofNullable(id); + } + + @JsonProperty("retry") + public Optional getRetry() { + return Optional.ofNullable(retry); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SseEvent sseEvent = (SseEvent) o; + return Objects.equals(event, sseEvent.event) + && Objects.equals(data, sseEvent.data) + && Objects.equals(id, sseEvent.id) + && Objects.equals(retry, sseEvent.retry); + } + + @Override + public int hashCode() { + return Objects.hash(event, data, id, retry); + } + + @Override + public String toString() { + return "SseEvent{" + "event='" + + event + '\'' + ", data=" + + data + ", id='" + + id + '\'' + ", retry=" + + retry + '}'; + } + + public static Builder builder() { + return new Builder<>(); + } + + public static final class Builder { + private String event; + private T data; + private String id; + private Long retry; + + private Builder() {} + + public Builder event(String event) { + this.event = event; + return this; + } + + public Builder data(T data) { + this.data = data; + return this; + } + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder retry(Long retry) { + this.retry = retry; + return this; + } + + public SseEvent build() { + return new SseEvent<>(event, data, id, retry); + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SseEventParser.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SseEventParser.java new file mode 100644 index 000000000000..8a379271adac --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/SseEventParser.java @@ -0,0 +1,228 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.core.type.TypeReference; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * Utility class for parsing Server-Sent Events with support for discriminated unions. + *

+ * Handles two discrimination patterns: + *

    + *
  1. Data-level discrimination: The discriminator (e.g., 'type') is inside the JSON data payload. + * Jackson's polymorphic deserialization handles this automatically.
  2. + *
  3. Event-level discrimination: The discriminator (e.g., 'event') is at the SSE envelope level. + * This requires constructing the full SSE envelope for Jackson to process.
  4. + *
+ */ +public final class SseEventParser { + + private static final Set SSE_ENVELOPE_FIELDS = new HashSet<>(Arrays.asList("event", "data", "id", "retry")); + + private SseEventParser() { + // Utility class + } + + /** + * Parse an SSE event using event-level discrimination. + *

+ * Constructs the full SSE envelope object with event, data, id, and retry fields, + * then deserializes it to the target union type. + * + * @param eventType The SSE event type (from event: field) + * @param data The SSE data content (from data: field) + * @param id The SSE event ID (from id: field), may be null + * @param retry The SSE retry value (from retry: field), may be null + * @param unionClass The target union class + * @param discriminatorProperty The property name used for discrimination (e.g., "event") + * @param The target type + * @return The deserialized object + */ + public static T parseEventLevelUnion( + String eventType, String data, String id, Long retry, Class unionClass, String discriminatorProperty) { + try { + // Determine if data should be parsed as JSON based on the variant's expected type + Object parsedData = parseDataForVariant(eventType, data, unionClass, discriminatorProperty); + + // Construct the SSE envelope object + Map envelope = new HashMap<>(); + envelope.put(discriminatorProperty, eventType); + envelope.put("data", parsedData); + if (id != null) { + envelope.put("id", id); + } + if (retry != null) { + envelope.put("retry", retry); + } + + // Serialize to JSON and deserialize to target type + String envelopeJson = ObjectMappers.JSON_MAPPER.writeValueAsString(envelope); + return ObjectMappers.JSON_MAPPER.readValue(envelopeJson, unionClass); + } catch (Exception e) { + throw new RuntimeException("Failed to parse SSE event with event-level discrimination", e); + } + } + + /** + * Parse an SSE event using data-level discrimination. + *

+ * Simply parses the data field as JSON and deserializes it to the target type. + * Jackson's polymorphic deserialization handles the discrimination automatically. + * + * @param data The SSE data content (from data: field) + * @param valueType The target type + * @param The target type + * @return The deserialized object + */ + public static T parseDataLevelUnion(String data, Class valueType) { + try { + return ObjectMappers.JSON_MAPPER.readValue(data, valueType); + } catch (Exception e) { + throw new RuntimeException("Failed to parse SSE data with data-level discrimination", e); + } + } + + /** + * Determines if the given discriminator property indicates event-level discrimination. + * Event-level discrimination occurs when the discriminator is an SSE envelope field. + * + * @param discriminatorProperty The discriminator property name + * @return true if event-level discrimination, false otherwise + */ + public static boolean isEventLevelDiscrimination(String discriminatorProperty) { + return SSE_ENVELOPE_FIELDS.contains(discriminatorProperty); + } + + /** + * Attempts to find the discriminator property from the union class's Jackson annotations. + * + * @param unionClass The union class to inspect + * @return The discriminator property name, or empty if not found + */ + public static Optional findDiscriminatorProperty(Class unionClass) { + try { + // Look for JsonTypeInfo on the class itself + JsonTypeInfo typeInfo = unionClass.getAnnotation(JsonTypeInfo.class); + if (typeInfo != null && !typeInfo.property().isEmpty()) { + return Optional.of(typeInfo.property()); + } + + // Look for inner Value interface with JsonTypeInfo + for (Class innerClass : unionClass.getDeclaredClasses()) { + typeInfo = innerClass.getAnnotation(JsonTypeInfo.class); + if (typeInfo != null && !typeInfo.property().isEmpty()) { + return Optional.of(typeInfo.property()); + } + } + } catch (Exception e) { + // Ignore reflection errors + } + return Optional.empty(); + } + + /** + * Parse the data field based on what the matching variant expects. + * If the variant expects a String for its data field, returns the raw string. + * Otherwise, parses the data as JSON. + */ + private static Object parseDataForVariant( + String eventType, String data, Class unionClass, String discriminatorProperty) { + if (data == null || data.isEmpty()) { + return data; + } + + try { + // Try to find the variant class that matches this event type + Class variantClass = findVariantClass(unionClass, eventType, discriminatorProperty); + if (variantClass != null) { + // Check if the variant expects a String for the data field + Field dataField = findField(variantClass, "data"); + if (dataField != null && String.class.equals(dataField.getType())) { + // Variant expects String - return raw data + return data; + } + } + + // Try to parse as JSON + return ObjectMappers.JSON_MAPPER.readValue(data, new TypeReference>() {}); + } catch (Exception e) { + // If JSON parsing fails, return as string + return data; + } + } + + /** + * Find the variant class that matches the given discriminator value. + */ + private static Class findVariantClass( + Class unionClass, String discriminatorValue, String discriminatorProperty) { + try { + // Look for JsonSubTypes annotation + JsonSubTypes subTypes = findJsonSubTypes(unionClass); + if (subTypes == null) { + return null; + } + + for (JsonSubTypes.Type subType : subTypes.value()) { + JsonTypeName typeName = subType.value().getAnnotation(JsonTypeName.class); + if (typeName != null && typeName.value().equals(discriminatorValue)) { + return subType.value(); + } + // Also check the name attribute of @JsonSubTypes.Type + if (subType.name().equals(discriminatorValue)) { + return subType.value(); + } + } + } catch (Exception e) { + // Ignore reflection errors + } + return null; + } + + /** + * Find JsonSubTypes annotation on the class or its inner classes. + */ + private static JsonSubTypes findJsonSubTypes(Class unionClass) { + // Check the class itself + JsonSubTypes subTypes = unionClass.getAnnotation(JsonSubTypes.class); + if (subTypes != null) { + return subTypes; + } + + // Check inner classes (for Fern-style unions with inner Value interface) + for (Class innerClass : unionClass.getDeclaredClasses()) { + subTypes = innerClass.getAnnotation(JsonSubTypes.class); + if (subTypes != null) { + return subTypes; + } + } + return null; + } + + /** + * Find a field by name in a class, including private fields. + */ + private static Field findField(Class clazz, String fieldName) { + try { + return clazz.getDeclaredField(fieldName); + } catch (NoSuchFieldException e) { + // Check superclass + Class superClass = clazz.getSuperclass(); + if (superClass != null && superClass != Object.class) { + return findField(superClass, fieldName); + } + return null; + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Stream.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Stream.java new file mode 100644 index 000000000000..ebc86490a594 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Stream.java @@ -0,0 +1,513 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.io.Closeable; +import java.io.IOException; +import java.io.Reader; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Scanner; + +/** + * The {@code Stream} class implements {@link Iterable} to provide a simple mechanism for reading and parsing + * objects of a given type from data streamed via a {@link Reader} using a specified delimiter. + *

+ * {@code Stream} assumes that data is being pushed to the provided {@link Reader} asynchronously and utilizes a + * {@code Scanner} to block during iteration if the next object is not available. + * Iterable stream for parsing JSON and Server-Sent Events (SSE) data. + * Supports both newline-delimited JSON and SSE with optional stream termination. + * + * @param The type of objects in the stream. + */ +public final class Stream implements Iterable, Closeable { + + private static final String NEWLINE = "\n"; + private static final String DATA_PREFIX = "data:"; + + public enum StreamType { + JSON, + SSE, + SSE_EVENT_DISCRIMINATED + } + + private final Class valueType; + private final Scanner scanner; + private final StreamType streamType; + private final String messageTerminator; + private final String streamTerminator; + private final Reader sseReader; + private final String discriminatorProperty; + private boolean isClosed = false; + + /** + * Constructs a new {@code Stream} with the specified value type, reader, and delimiter. + * + * @param valueType The class of the objects in the stream. + * @param reader The reader that provides the streamed data. + * @param delimiter The delimiter used to separate elements in the stream. + */ + public Stream(Class valueType, Reader reader, String delimiter) { + this.valueType = valueType; + this.scanner = new Scanner(reader).useDelimiter(delimiter); + this.streamType = StreamType.JSON; + this.messageTerminator = delimiter; + this.streamTerminator = null; + this.sseReader = null; + this.discriminatorProperty = null; + } + + private Stream(Class valueType, StreamType type, Reader reader, String terminator) { + this(valueType, type, reader, terminator, null); + } + + private Stream( + Class valueType, StreamType type, Reader reader, String terminator, String discriminatorProperty) { + this.valueType = valueType; + this.streamType = type; + this.discriminatorProperty = discriminatorProperty; + if (type == StreamType.JSON) { + this.scanner = new Scanner(reader).useDelimiter(terminator); + this.messageTerminator = terminator; + this.streamTerminator = null; + this.sseReader = null; + } else { + this.scanner = null; + this.messageTerminator = NEWLINE; + this.streamTerminator = terminator; + this.sseReader = reader; + } + } + + public static Stream fromJson(Class valueType, Reader reader, String delimiter) { + return new Stream<>(valueType, reader, delimiter); + } + + public static Stream fromJson(Class valueType, Reader reader) { + return new Stream<>(valueType, reader, NEWLINE); + } + + public static Stream fromSse(Class valueType, Reader sseReader) { + return new Stream<>(valueType, StreamType.SSE, sseReader, null); + } + + public static Stream fromSse(Class valueType, Reader sseReader, String streamTerminator) { + return new Stream<>(valueType, StreamType.SSE, sseReader, streamTerminator); + } + + /** + * Creates a stream from SSE data with event-level discrimination support. + * Use this when the SSE payload is a discriminated union where the discriminator + * is an SSE envelope field (e.g., 'event'). + * + * @param valueType The class of the objects in the stream. + * @param sseReader The reader that provides the SSE data. + * @param discriminatorProperty The property name used for discrimination (e.g., "event"). + * @param The type of objects in the stream. + * @return A new Stream instance configured for SSE with event-level discrimination. + */ + public static Stream fromSseWithEventDiscrimination( + Class valueType, Reader sseReader, String discriminatorProperty) { + return new Stream<>(valueType, StreamType.SSE_EVENT_DISCRIMINATED, sseReader, null, discriminatorProperty); + } + + /** + * Creates a stream from SSE data with event-level discrimination support and a stream terminator. + * + * @param valueType The class of the objects in the stream. + * @param sseReader The reader that provides the SSE data. + * @param discriminatorProperty The property name used for discrimination (e.g., "event"). + * @param streamTerminator The terminator string that signals end of stream (e.g., "[DONE]"). + * @param The type of objects in the stream. + * @return A new Stream instance configured for SSE with event-level discrimination. + */ + public static Stream fromSseWithEventDiscrimination( + Class valueType, Reader sseReader, String discriminatorProperty, String streamTerminator) { + return new Stream<>( + valueType, StreamType.SSE_EVENT_DISCRIMINATED, sseReader, streamTerminator, discriminatorProperty); + } + + @Override + public void close() throws IOException { + if (!isClosed) { + isClosed = true; + if (scanner != null) { + scanner.close(); + } + if (sseReader != null) { + sseReader.close(); + } + } + } + + private boolean isStreamClosed() { + return isClosed; + } + + /** + * Returns an iterator over the elements in this stream that blocks during iteration when the next object is + * not yet available. + * + * @return An iterator that can be used to traverse the elements in the stream. + */ + @Override + public Iterator iterator() { + switch (streamType) { + case SSE: + return new SSEIterator(); + case SSE_EVENT_DISCRIMINATED: + return new SSEEventDiscriminatedIterator(); + case JSON: + default: + return new JsonIterator(); + } + } + + private final class JsonIterator implements Iterator { + + /** + * Returns {@code true} if there are more elements in the stream. + *

+ * Will block and wait for input if the stream has not ended and the next object is not yet available. + * + * @return {@code true} if there are more elements, {@code false} otherwise. + */ + @Override + public boolean hasNext() { + if (isStreamClosed()) { + return false; + } + return scanner.hasNext(); + } + + /** + * Returns the next element in the stream. + *

+ * Will block and wait for input if the stream has not ended and the next object is not yet available. + * + * @return The next element in the stream. + * @throws NoSuchElementException If there are no more elements in the stream. + */ + @Override + public T next() { + if (isStreamClosed()) { + throw new NoSuchElementException("Stream is closed"); + } + + if (!scanner.hasNext()) { + throw new NoSuchElementException(); + } else { + try { + T parsedResponse = + ObjectMappers.JSON_MAPPER.readValue(scanner.next().trim(), valueType); + return parsedResponse; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + private final class SSEIterator implements Iterator { + private Scanner sseScanner; + private T nextItem; + private boolean hasNextItem = false; + private boolean endOfStream = false; + private StringBuilder eventDataBuffer = new StringBuilder(); + private String currentEventType = null; + + private SSEIterator() { + if (sseReader != null && !isStreamClosed()) { + this.sseScanner = new Scanner(sseReader); + } else { + this.endOfStream = true; + } + } + + @Override + public boolean hasNext() { + if (isStreamClosed() || endOfStream) { + return false; + } + + if (hasNextItem) { + return true; + } + + return readNextMessage(); + } + + @Override + public T next() { + if (!hasNext()) { + throw new NoSuchElementException("No more elements in stream"); + } + + T result = nextItem; + nextItem = null; + hasNextItem = false; + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + private boolean readNextMessage() { + if (sseScanner == null || isStreamClosed()) { + endOfStream = true; + return false; + } + + try { + while (sseScanner.hasNextLine()) { + String line = sseScanner.nextLine(); + + if (line.trim().isEmpty()) { + if (eventDataBuffer.length() > 0) { + try { + nextItem = ObjectMappers.JSON_MAPPER.readValue(eventDataBuffer.toString(), valueType); + hasNextItem = true; + eventDataBuffer.setLength(0); + currentEventType = null; + return true; + } catch (Exception parseEx) { + System.err.println("Failed to parse SSE event: " + parseEx.getMessage()); + eventDataBuffer.setLength(0); + currentEventType = null; + continue; + } + } + continue; + } + + if (line.startsWith(DATA_PREFIX)) { + String dataContent = line.substring(DATA_PREFIX.length()); + if (dataContent.startsWith(" ")) { + dataContent = dataContent.substring(1); + } + + if (eventDataBuffer.length() == 0 + && streamTerminator != null + && dataContent.trim().equals(streamTerminator)) { + endOfStream = true; + return false; + } + + if (eventDataBuffer.length() > 0) { + eventDataBuffer.append('\n'); + } + eventDataBuffer.append(dataContent); + } else if (line.startsWith("event:")) { + String eventValue = line.length() > 6 ? line.substring(6) : ""; + if (eventValue.startsWith(" ")) { + eventValue = eventValue.substring(1); + } + currentEventType = eventValue; + } else if (line.startsWith("id:")) { + // Event ID field (ignored) + } else if (line.startsWith("retry:")) { + // Retry field (ignored) + } else if (line.startsWith(":")) { + // Comment line (ignored) + } + } + + if (eventDataBuffer.length() > 0) { + try { + nextItem = ObjectMappers.JSON_MAPPER.readValue(eventDataBuffer.toString(), valueType); + hasNextItem = true; + eventDataBuffer.setLength(0); + currentEventType = null; + return true; + } catch (Exception parseEx) { + System.err.println("Failed to parse final SSE event: " + parseEx.getMessage()); + eventDataBuffer.setLength(0); + currentEventType = null; + } + } + + endOfStream = true; + return false; + + } catch (Exception e) { + System.err.println("Failed to parse SSE stream: " + e.getMessage()); + endOfStream = true; + return false; + } + } + } + + /** + * Iterator for SSE streams with event-level discrimination. + * Uses SseEventParser to construct the full SSE envelope for Jackson deserialization. + */ + private final class SSEEventDiscriminatedIterator implements Iterator { + private Scanner sseScanner; + private T nextItem; + private boolean hasNextItem = false; + private boolean endOfStream = false; + private StringBuilder eventDataBuffer = new StringBuilder(); + private String currentEventType = null; + private String currentEventId = null; + private Long currentRetry = null; + + private SSEEventDiscriminatedIterator() { + if (sseReader != null && !isStreamClosed()) { + this.sseScanner = new Scanner(sseReader); + } else { + this.endOfStream = true; + } + } + + @Override + public boolean hasNext() { + if (isStreamClosed() || endOfStream) { + return false; + } + + if (hasNextItem) { + return true; + } + + return readNextMessage(); + } + + @Override + public T next() { + if (!hasNext()) { + throw new NoSuchElementException("No more elements in stream"); + } + + T result = nextItem; + nextItem = null; + hasNextItem = false; + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + private boolean readNextMessage() { + if (sseScanner == null || isStreamClosed()) { + endOfStream = true; + return false; + } + + try { + while (sseScanner.hasNextLine()) { + String line = sseScanner.nextLine(); + + if (line.trim().isEmpty()) { + if (eventDataBuffer.length() > 0 || currentEventType != null) { + try { + // Use SseEventParser for event-level discrimination + nextItem = SseEventParser.parseEventLevelUnion( + currentEventType, + eventDataBuffer.toString(), + currentEventId, + currentRetry, + valueType, + discriminatorProperty); + hasNextItem = true; + resetEventState(); + return true; + } catch (Exception parseEx) { + System.err.println("Failed to parse SSE event: " + parseEx.getMessage()); + resetEventState(); + continue; + } + } + continue; + } + + if (line.startsWith(DATA_PREFIX)) { + String dataContent = line.substring(DATA_PREFIX.length()); + if (dataContent.startsWith(" ")) { + dataContent = dataContent.substring(1); + } + + if (eventDataBuffer.length() == 0 + && streamTerminator != null + && dataContent.trim().equals(streamTerminator)) { + endOfStream = true; + return false; + } + + if (eventDataBuffer.length() > 0) { + eventDataBuffer.append('\n'); + } + eventDataBuffer.append(dataContent); + } else if (line.startsWith("event:")) { + String eventValue = line.length() > 6 ? line.substring(6) : ""; + if (eventValue.startsWith(" ")) { + eventValue = eventValue.substring(1); + } + currentEventType = eventValue; + } else if (line.startsWith("id:")) { + String idValue = line.length() > 3 ? line.substring(3) : ""; + if (idValue.startsWith(" ")) { + idValue = idValue.substring(1); + } + currentEventId = idValue; + } else if (line.startsWith("retry:")) { + String retryValue = line.length() > 6 ? line.substring(6) : ""; + if (retryValue.startsWith(" ")) { + retryValue = retryValue.substring(1); + } + try { + currentRetry = Long.parseLong(retryValue.trim()); + } catch (NumberFormatException e) { + // Ignore invalid retry values + } + } else if (line.startsWith(":")) { + // Comment line (ignored) + } + } + + // Handle any remaining buffered data at end of stream + if (eventDataBuffer.length() > 0 || currentEventType != null) { + try { + nextItem = SseEventParser.parseEventLevelUnion( + currentEventType, + eventDataBuffer.toString(), + currentEventId, + currentRetry, + valueType, + discriminatorProperty); + hasNextItem = true; + resetEventState(); + return true; + } catch (Exception parseEx) { + System.err.println("Failed to parse final SSE event: " + parseEx.getMessage()); + resetEventState(); + } + } + + endOfStream = true; + return false; + + } catch (Exception e) { + System.err.println("Failed to parse SSE stream: " + e.getMessage()); + endOfStream = true; + return false; + } + } + + private void resetEventState() { + eventDataBuffer.setLength(0); + currentEventType = null; + currentEventId = null; + currentRetry = null; + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Suppliers.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Suppliers.java new file mode 100644 index 000000000000..9f137d9f03c6 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/core/Suppliers.java @@ -0,0 +1,23 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; + +public final class Suppliers { + private Suppliers() {} + + public static Supplier memoize(Supplier delegate) { + AtomicReference value = new AtomicReference<>(); + return () -> { + T val = value.get(); + if (val == null) { + val = value.updateAndGet(cur -> cur == null ? Objects.requireNonNull(delegate.get()) : cur); + } + return val; + }; + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/AsyncDummyClient.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/AsyncDummyClient.java new file mode 100644 index 000000000000..92e60e8e1561 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/AsyncDummyClient.java @@ -0,0 +1,37 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.resources.dummy; + +import com.seed.streaming.core.ClientOptions; +import com.seed.streaming.core.RequestOptions; +import com.seed.streaming.resources.dummy.requests.GenerateRequest; +import com.seed.streaming.resources.dummy.types.StreamResponse; +import java.util.concurrent.CompletableFuture; + +public class AsyncDummyClient { + protected final ClientOptions clientOptions; + + private final AsyncRawDummyClient rawClient; + + public AsyncDummyClient(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + this.rawClient = new AsyncRawDummyClient(clientOptions); + } + + /** + * Get responses with HTTP metadata like headers + */ + public AsyncRawDummyClient withRawResponse() { + return this.rawClient; + } + + public CompletableFuture> generate(GenerateRequest request) { + return this.rawClient.generate(request).thenApply(response -> response.body()); + } + + public CompletableFuture> generate( + GenerateRequest request, RequestOptions requestOptions) { + return this.rawClient.generate(request, requestOptions).thenApply(response -> response.body()); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/AsyncRawDummyClient.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/AsyncRawDummyClient.java new file mode 100644 index 000000000000..4aebf471c9c1 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/AsyncRawDummyClient.java @@ -0,0 +1,100 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.resources.dummy; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.seed.streaming.core.ClientOptions; +import com.seed.streaming.core.MediaTypes; +import com.seed.streaming.core.ObjectMappers; +import com.seed.streaming.core.RequestOptions; +import com.seed.streaming.core.ResponseBodyReader; +import com.seed.streaming.core.SeedStreamingApiException; +import com.seed.streaming.core.SeedStreamingException; +import com.seed.streaming.core.SeedStreamingHttpResponse; +import com.seed.streaming.core.Stream; +import com.seed.streaming.resources.dummy.requests.GenerateRequest; +import com.seed.streaming.resources.dummy.types.StreamResponse; +import java.io.IOException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Headers; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; +import org.jetbrains.annotations.NotNull; + +public class AsyncRawDummyClient { + protected final ClientOptions clientOptions; + + public AsyncRawDummyClient(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + } + + public CompletableFuture>> generate(GenerateRequest request) { + return generate(request, null); + } + + public CompletableFuture>> generate( + GenerateRequest request, RequestOptions requestOptions) { + HttpUrl.Builder httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) + .newBuilder() + .addPathSegments("generate"); + if (requestOptions != null) { + requestOptions.getQueryParameters().forEach((_key, _value) -> { + httpUrl.addQueryParameter(_key, _value); + }); + } + RequestBody body; + try { + body = RequestBody.create( + ObjectMappers.JSON_MAPPER.writeValueAsBytes(request), MediaTypes.APPLICATION_JSON); + } catch (JsonProcessingException e) { + throw new SeedStreamingException("Failed to serialize request", e); + } + Request okhttpRequest = new Request.Builder() + .url(httpUrl.build()) + .method("POST", body) + .headers(Headers.of(clientOptions.headers(requestOptions))) + .addHeader("Content-Type", "application/json") + .build(); + OkHttpClient client = clientOptions.httpClient(); + if (requestOptions != null && requestOptions.getTimeout().isPresent()) { + client = clientOptions.httpClientWithTimeout(requestOptions); + } + client = client.newBuilder().callTimeout(0, TimeUnit.SECONDS).build(); + CompletableFuture>> future = new CompletableFuture<>(); + client.newCall(okhttpRequest).enqueue(new Callback() { + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { + try { + ResponseBody responseBody = response.body(); + if (response.isSuccessful()) { + future.complete(new SeedStreamingHttpResponse<>( + Stream.fromJson(StreamResponse.class, new ResponseBodyReader(response), "\\n"), + response)); + return; + } + String responseBodyString = responseBody != null ? responseBody.string() : "{}"; + Object errorBody = ObjectMappers.parseErrorBody(responseBodyString); + future.completeExceptionally(new SeedStreamingApiException( + "Error with status code " + response.code(), response.code(), errorBody, response)); + return; + } catch (IOException e) { + future.completeExceptionally(new SeedStreamingException("Network error executing HTTP request", e)); + } + } + + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + future.completeExceptionally(new SeedStreamingException("Network error executing HTTP request", e)); + } + }); + return future; + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/DummyClient.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/DummyClient.java new file mode 100644 index 000000000000..73591656512f --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/DummyClient.java @@ -0,0 +1,35 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.resources.dummy; + +import com.seed.streaming.core.ClientOptions; +import com.seed.streaming.core.RequestOptions; +import com.seed.streaming.resources.dummy.requests.GenerateRequest; +import com.seed.streaming.resources.dummy.types.StreamResponse; + +public class DummyClient { + protected final ClientOptions clientOptions; + + private final RawDummyClient rawClient; + + public DummyClient(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + this.rawClient = new RawDummyClient(clientOptions); + } + + /** + * Get responses with HTTP metadata like headers + */ + public RawDummyClient withRawResponse() { + return this.rawClient; + } + + public Iterable generate(GenerateRequest request) { + return this.rawClient.generate(request).body(); + } + + public Iterable generate(GenerateRequest request, RequestOptions requestOptions) { + return this.rawClient.generate(request, requestOptions).body(); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/RawDummyClient.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/RawDummyClient.java new file mode 100644 index 000000000000..9e7102355045 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/RawDummyClient.java @@ -0,0 +1,82 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.resources.dummy; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.seed.streaming.core.ClientOptions; +import com.seed.streaming.core.MediaTypes; +import com.seed.streaming.core.ObjectMappers; +import com.seed.streaming.core.RequestOptions; +import com.seed.streaming.core.ResponseBodyReader; +import com.seed.streaming.core.SeedStreamingApiException; +import com.seed.streaming.core.SeedStreamingException; +import com.seed.streaming.core.SeedStreamingHttpResponse; +import com.seed.streaming.core.Stream; +import com.seed.streaming.resources.dummy.requests.GenerateRequest; +import com.seed.streaming.resources.dummy.types.StreamResponse; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import okhttp3.Headers; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; + +public class RawDummyClient { + protected final ClientOptions clientOptions; + + public RawDummyClient(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + } + + public SeedStreamingHttpResponse> generate(GenerateRequest request) { + return generate(request, null); + } + + public SeedStreamingHttpResponse> generate( + GenerateRequest request, RequestOptions requestOptions) { + HttpUrl.Builder httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) + .newBuilder() + .addPathSegments("generate"); + if (requestOptions != null) { + requestOptions.getQueryParameters().forEach((_key, _value) -> { + httpUrl.addQueryParameter(_key, _value); + }); + } + RequestBody body; + try { + body = RequestBody.create( + ObjectMappers.JSON_MAPPER.writeValueAsBytes(request), MediaTypes.APPLICATION_JSON); + } catch (JsonProcessingException e) { + throw new SeedStreamingException("Failed to serialize request", e); + } + Request okhttpRequest = new Request.Builder() + .url(httpUrl.build()) + .method("POST", body) + .headers(Headers.of(clientOptions.headers(requestOptions))) + .addHeader("Content-Type", "application/json") + .build(); + OkHttpClient client = clientOptions.httpClient(); + if (requestOptions != null && requestOptions.getTimeout().isPresent()) { + client = clientOptions.httpClientWithTimeout(requestOptions); + } + client = client.newBuilder().callTimeout(0, TimeUnit.SECONDS).build(); + try { + Response response = client.newCall(okhttpRequest).execute(); + ResponseBody responseBody = response.body(); + if (response.isSuccessful()) { + return new SeedStreamingHttpResponse<>( + Stream.fromJson(StreamResponse.class, new ResponseBodyReader(response), "\\n"), response); + } + String responseBodyString = responseBody != null ? responseBody.string() : "{}"; + Object errorBody = ObjectMappers.parseErrorBody(responseBodyString); + throw new SeedStreamingApiException( + "Error with status code " + response.code(), response.code(), errorBody, response); + } catch (IOException e) { + throw new SeedStreamingException("Network error executing HTTP request", e); + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/requests/GenerateRequest.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/requests/GenerateRequest.java new file mode 100644 index 000000000000..3e65f93644f7 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/requests/GenerateRequest.java @@ -0,0 +1,139 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.resources.dummy.requests; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.seed.streaming.core.ObjectMappers; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = GenerateRequest.Builder.class) +public final class GenerateRequest { + private final boolean stream; + + private final int numEvents; + + private final Map additionalProperties; + + private GenerateRequest(boolean stream, int numEvents, Map additionalProperties) { + this.stream = stream; + this.numEvents = numEvents; + this.additionalProperties = additionalProperties; + } + + @JsonProperty("stream") + public boolean getStream() { + return stream; + } + + @JsonProperty("num_events") + public int getNumEvents() { + return numEvents; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof GenerateRequest && equalTo((GenerateRequest) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(GenerateRequest other) { + return stream == other.stream && numEvents == other.numEvents; + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.stream, this.numEvents); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static StreamStage builder() { + return new Builder(); + } + + public interface StreamStage { + NumEventsStage stream(boolean stream); + + Builder from(GenerateRequest other); + } + + public interface NumEventsStage { + _FinalStage numEvents(int numEvents); + } + + public interface _FinalStage { + GenerateRequest build(); + + _FinalStage additionalProperty(String key, Object value); + + _FinalStage additionalProperties(Map additionalProperties); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder implements StreamStage, NumEventsStage, _FinalStage { + private boolean stream; + + private int numEvents; + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + @java.lang.Override + public Builder from(GenerateRequest other) { + stream(other.getStream()); + numEvents(other.getNumEvents()); + return this; + } + + @java.lang.Override + @JsonSetter("stream") + public NumEventsStage stream(boolean stream) { + this.stream = stream; + return this; + } + + @java.lang.Override + @JsonSetter("num_events") + public _FinalStage numEvents(int numEvents) { + this.numEvents = numEvents; + return this; + } + + @java.lang.Override + public GenerateRequest build() { + return new GenerateRequest(stream, numEvents, additionalProperties); + } + + @java.lang.Override + public Builder additionalProperty(String key, Object value) { + this.additionalProperties.put(key, value); + return this; + } + + @java.lang.Override + public Builder additionalProperties(Map additionalProperties) { + this.additionalProperties.putAll(additionalProperties); + return this; + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/types/RegularResponse.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/types/RegularResponse.java new file mode 100644 index 000000000000..5b74c5809ce2 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/types/RegularResponse.java @@ -0,0 +1,148 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.resources.dummy.types; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.seed.streaming.core.ObjectMappers; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import org.jetbrains.annotations.NotNull; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = RegularResponse.Builder.class) +public final class RegularResponse { + private final String id; + + private final Optional name; + + private final Map additionalProperties; + + private RegularResponse(String id, Optional name, Map additionalProperties) { + this.id = id; + this.name = name; + this.additionalProperties = additionalProperties; + } + + @JsonProperty("id") + public String getId() { + return id; + } + + @JsonProperty("name") + public Optional getName() { + return name; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof RegularResponse && equalTo((RegularResponse) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(RegularResponse other) { + return id.equals(other.id) && name.equals(other.name); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.id, this.name); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static IdStage builder() { + return new Builder(); + } + + public interface IdStage { + _FinalStage id(@NotNull String id); + + Builder from(RegularResponse other); + } + + public interface _FinalStage { + RegularResponse build(); + + _FinalStage additionalProperty(String key, Object value); + + _FinalStage additionalProperties(Map additionalProperties); + + _FinalStage name(Optional name); + + _FinalStage name(String name); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder implements IdStage, _FinalStage { + private String id; + + private Optional name = Optional.empty(); + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + @java.lang.Override + public Builder from(RegularResponse other) { + id(other.getId()); + name(other.getName()); + return this; + } + + @java.lang.Override + @JsonSetter("id") + public _FinalStage id(@NotNull String id) { + this.id = Objects.requireNonNull(id, "id must not be null"); + return this; + } + + @java.lang.Override + public _FinalStage name(String name) { + this.name = Optional.ofNullable(name); + return this; + } + + @java.lang.Override + @JsonSetter(value = "name", nulls = Nulls.SKIP) + public _FinalStage name(Optional name) { + this.name = name; + return this; + } + + @java.lang.Override + public RegularResponse build() { + return new RegularResponse(id, name, additionalProperties); + } + + @java.lang.Override + public Builder additionalProperty(String key, Object value) { + this.additionalProperties.put(key, value); + return this; + } + + @java.lang.Override + public Builder additionalProperties(Map additionalProperties) { + this.additionalProperties.putAll(additionalProperties); + return this; + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/types/StreamResponse.java b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/types/StreamResponse.java new file mode 100644 index 000000000000..d60e0767fdbc --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/seed/streaming/resources/dummy/types/StreamResponse.java @@ -0,0 +1,148 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.resources.dummy.types; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.seed.streaming.core.ObjectMappers; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import org.jetbrains.annotations.NotNull; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = StreamResponse.Builder.class) +public final class StreamResponse { + private final String id; + + private final Optional name; + + private final Map additionalProperties; + + private StreamResponse(String id, Optional name, Map additionalProperties) { + this.id = id; + this.name = name; + this.additionalProperties = additionalProperties; + } + + @JsonProperty("id") + public String getId() { + return id; + } + + @JsonProperty("name") + public Optional getName() { + return name; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof StreamResponse && equalTo((StreamResponse) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(StreamResponse other) { + return id.equals(other.id) && name.equals(other.name); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.id, this.name); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static IdStage builder() { + return new Builder(); + } + + public interface IdStage { + _FinalStage id(@NotNull String id); + + Builder from(StreamResponse other); + } + + public interface _FinalStage { + StreamResponse build(); + + _FinalStage additionalProperty(String key, Object value); + + _FinalStage additionalProperties(Map additionalProperties); + + _FinalStage name(Optional name); + + _FinalStage name(String name); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder implements IdStage, _FinalStage { + private String id; + + private Optional name = Optional.empty(); + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + @java.lang.Override + public Builder from(StreamResponse other) { + id(other.getId()); + name(other.getName()); + return this; + } + + @java.lang.Override + @JsonSetter("id") + public _FinalStage id(@NotNull String id) { + this.id = Objects.requireNonNull(id, "id must not be null"); + return this; + } + + @java.lang.Override + public _FinalStage name(String name) { + this.name = Optional.ofNullable(name); + return this; + } + + @java.lang.Override + @JsonSetter(value = "name", nulls = Nulls.SKIP) + public _FinalStage name(Optional name) { + this.name = name; + return this; + } + + @java.lang.Override + public StreamResponse build() { + return new StreamResponse(id, name, additionalProperties); + } + + @java.lang.Override + public Builder additionalProperty(String key, Object value) { + this.additionalProperties.put(key, value); + return this; + } + + @java.lang.Override + public Builder additionalProperties(Map additionalProperties) { + this.additionalProperties.putAll(additionalProperties); + return this; + } + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/snippets/Example0.java b/seed/java-sdk/streaming-parameter/src/main/java/com/snippets/Example0.java new file mode 100644 index 000000000000..123c880780a3 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/snippets/Example0.java @@ -0,0 +1,14 @@ +package com.snippets; + +import com.seed.streaming.SeedStreamingClient; +import com.seed.streaming.resources.dummy.requests.GenerateRequest; + +public class Example0 { + public static void main(String[] args) { + SeedStreamingClient client = + SeedStreamingClient.builder().url("https://api.fern.com").build(); + + client.dummy() + .generate(GenerateRequest.builder().stream(false).numEvents(5).build()); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/main/java/com/snippets/Example1.java b/seed/java-sdk/streaming-parameter/src/main/java/com/snippets/Example1.java new file mode 100644 index 000000000000..a5dd02689f17 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/main/java/com/snippets/Example1.java @@ -0,0 +1,14 @@ +package com.snippets; + +import com.seed.streaming.SeedStreamingClient; +import com.seed.streaming.resources.dummy.requests.GenerateRequest; + +public class Example1 { + public static void main(String[] args) { + SeedStreamingClient client = + SeedStreamingClient.builder().url("https://api.fern.com").build(); + + client.dummy() + .generate(GenerateRequest.builder().stream(true).numEvents(1).build()); + } +} diff --git a/seed/java-sdk/streaming-parameter/src/test/java/com/seed/streaming/StreamTest.java b/seed/java-sdk/streaming-parameter/src/test/java/com/seed/streaming/StreamTest.java new file mode 100644 index 000000000000..3b8ab0e8a8c6 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/test/java/com/seed/streaming/StreamTest.java @@ -0,0 +1,120 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming; + +import static org.junit.jupiter.api.Assertions.*; + +import com.seed.streaming.core.ObjectMappers; +import com.seed.streaming.core.Stream; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Test; + +public final class StreamTest { + @Test + public void testJsonStream() { + List> messages = + Arrays.asList(createMap("message", "hello"), createMap("message", "world")); + List jsonStrings = messages.stream().map(StreamTest::mapToJson).collect(Collectors.toList()); + String input = String.join("\n", jsonStrings); + StringReader jsonInput = new StringReader(input); + Stream jsonStream = Stream.fromJson(Map.class, jsonInput); + int expectedMessages = 2; + int actualMessages = 0; + for (Map jsonObject : jsonStream) { + actualMessages++; + assertTrue(jsonObject.containsKey("message")); + } + assertEquals(expectedMessages, actualMessages); + } + + @Test + public void testSseStream() { + List> events = Arrays.asList(createMap("event", "start"), createMap("event", "end")); + List sseStrings = events.stream().map(StreamTest::mapToSse).collect(Collectors.toList()); + String input = String.join("\n" + "\n", sseStrings); + StringReader sseInput = new StringReader(input); + Stream sseStream = Stream.fromSse(Map.class, sseInput); + int expectedEvents = 2; + int actualEvents = 0; + for (Map eventData : sseStream) { + actualEvents++; + assertTrue(eventData.containsKey("event")); + } + assertEquals(expectedEvents, actualEvents); + } + + @Test + public void testSseStreamWithTerminator() { + List> events = Arrays.asList(createMap("message", "first"), createMap("message", "second")); + List sseStrings = + new ArrayList<>(events.stream().map(StreamTest::mapToSse).collect(Collectors.toList())); + sseStrings.add("data: [DONE]"); + String input = String.join("\n" + "\n", sseStrings); + StringReader sseInput = new StringReader(input); + Stream sseStream = Stream.fromSse(Map.class, sseInput, "[DONE]"); + int expectedEvents = 2; + int actualEvents = 0; + for (Map eventData : sseStream) { + actualEvents++; + assertTrue(eventData.containsKey("message")); + } + assertEquals(expectedEvents, actualEvents); + } + + @Test + public void testSseEventDiscriminatedStream() { + List sseStrings = Arrays.asList( + mapToSseWithEvent("start", createMap("status", "pending")), + mapToSseWithEvent("end", createMap("status", "complete"))); + String input = String.join("\n" + "\n", sseStrings); + StringReader sseInput = new StringReader(input); + Stream sseStream = Stream.fromSseWithEventDiscrimination(Map.class, sseInput, "event"); + int expectedEvents = 2; + int actualEvents = 0; + for (Map eventData : sseStream) { + actualEvents++; + // Event-level discrimination includes the event field in the parsed result + assertTrue(eventData.containsKey("event")); + assertTrue(eventData.containsKey("data")); + } + assertEquals(expectedEvents, actualEvents); + } + + @Test + public void testStreamResourceManagement() throws IOException { + StringReader testInput = new StringReader("{\"test\":\"data\"}"); + Stream testStream = Stream.fromJson(Map.class, testInput); + testStream.close(); + assertFalse(testStream.iterator().hasNext()); + } + + private static String mapToJson(Map map) { + try { + return ObjectMappers.JSON_MAPPER.writeValueAsString(map); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static String mapToSse(Map map) { + return "data: " + mapToJson(map); + } + + private static String mapToSseWithEvent(String eventType, Map data) { + return "event: " + eventType + "\n" + "data: " + mapToJson(data); + } + + private static Map createMap(String key, String value) { + Map map = new HashMap<>(); + map.put(key, value); + return map; + } +} diff --git a/seed/java-sdk/streaming-parameter/src/test/java/com/seed/streaming/TestClient.java b/seed/java-sdk/streaming-parameter/src/test/java/com/seed/streaming/TestClient.java new file mode 100644 index 000000000000..424830408da9 --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/test/java/com/seed/streaming/TestClient.java @@ -0,0 +1,11 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming; + +public final class TestClient { + public void test() { + // Add tests here and mark this file in .fernignore + assert true; + } +} diff --git a/seed/java-sdk/streaming-parameter/src/test/java/com/seed/streaming/core/QueryStringMapperTest.java b/seed/java-sdk/streaming-parameter/src/test/java/com/seed/streaming/core/QueryStringMapperTest.java new file mode 100644 index 000000000000..6daf801d1d6f --- /dev/null +++ b/seed/java-sdk/streaming-parameter/src/test/java/com/seed/streaming/core/QueryStringMapperTest.java @@ -0,0 +1,339 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.streaming.core; + +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import okhttp3.HttpUrl; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public final class QueryStringMapperTest { + @Test + public void testObjectWithQuotedString_indexedArrays() { + Map map = new HashMap() { + { + put("hello", "\"world\""); + } + }; + + String expectedQueryString = "withquoted%5Bhello%5D=%22world%22"; + + String actualQueryString = queryString( + new HashMap() { + { + put("withquoted", map); + } + }, + false); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + @Test + public void testObjectWithQuotedString_arraysAsRepeats() { + Map map = new HashMap() { + { + put("hello", "\"world\""); + } + }; + + String expectedQueryString = "withquoted%5Bhello%5D=%22world%22"; + + String actualQueryString = queryString( + new HashMap() { + { + put("withquoted", map); + } + }, + true); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + @Test + public void testObject_indexedArrays() { + Map map = new HashMap() { + { + put("foo", "bar"); + put("baz", "qux"); + } + }; + + String expectedQueryString = "metadata%5Bfoo%5D=bar&metadata%5Bbaz%5D=qux"; + + String actualQueryString = queryString( + new HashMap() { + { + put("metadata", map); + } + }, + false); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + @Test + public void testObject_arraysAsRepeats() { + Map map = new HashMap() { + { + put("foo", "bar"); + put("baz", "qux"); + } + }; + + String expectedQueryString = "metadata%5Bfoo%5D=bar&metadata%5Bbaz%5D=qux"; + + String actualQueryString = queryString( + new HashMap() { + { + put("metadata", map); + } + }, + true); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + @Test + public void testNestedObject_indexedArrays() { + Map> nestedMap = new HashMap>() { + { + put("mapkey1", new HashMap() { + { + put("mapkey1mapkey1", "mapkey1mapkey1value"); + put("mapkey1mapkey2", "mapkey1mapkey2value"); + } + }); + put("mapkey2", new HashMap() { + { + put("mapkey2mapkey1", "mapkey2mapkey1value"); + } + }); + } + }; + + String expectedQueryString = + "nested%5Bmapkey2%5D%5Bmapkey2mapkey1%5D=mapkey2mapkey1value&nested%5Bmapkey1%5D%5Bmapkey1mapkey1" + + "%5D=mapkey1mapkey1value&nested%5Bmapkey1%5D%5Bmapkey1mapkey2%5D=mapkey1mapkey2value"; + + String actualQueryString = queryString( + new HashMap() { + { + put("nested", nestedMap); + } + }, + false); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + @Test + public void testNestedObject_arraysAsRepeats() { + Map> nestedMap = new HashMap>() { + { + put("mapkey1", new HashMap() { + { + put("mapkey1mapkey1", "mapkey1mapkey1value"); + put("mapkey1mapkey2", "mapkey1mapkey2value"); + } + }); + put("mapkey2", new HashMap() { + { + put("mapkey2mapkey1", "mapkey2mapkey1value"); + } + }); + } + }; + + String expectedQueryString = + "nested%5Bmapkey2%5D%5Bmapkey2mapkey1%5D=mapkey2mapkey1value&nested%5Bmapkey1%5D%5Bmapkey1mapkey1" + + "%5D=mapkey1mapkey1value&nested%5Bmapkey1%5D%5Bmapkey1mapkey2%5D=mapkey1mapkey2value"; + + String actualQueryString = queryString( + new HashMap() { + { + put("nested", nestedMap); + } + }, + true); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + @Test + public void testDateTime_indexedArrays() { + OffsetDateTime dateTime = + OffsetDateTime.ofInstant(Instant.ofEpochSecond(1740412107L), ZoneId.of("America/New_York")); + + String expectedQueryString = "datetime=2025-02-24T10%3A48%3A27-05%3A00"; + + String actualQueryString = queryString( + new HashMap() { + { + put("datetime", dateTime); + } + }, + false); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + @Test + public void testDateTime_arraysAsRepeats() { + OffsetDateTime dateTime = + OffsetDateTime.ofInstant(Instant.ofEpochSecond(1740412107L), ZoneId.of("America/New_York")); + + String expectedQueryString = "datetime=2025-02-24T10%3A48%3A27-05%3A00"; + + String actualQueryString = queryString( + new HashMap() { + { + put("datetime", dateTime); + } + }, + true); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + @Test + public void testObjectArray_indexedArrays() { + List> mapArray = new ArrayList>() { + { + add(new HashMap() { + { + put("key", "hello"); + put("value", "world"); + } + }); + add(new HashMap() { + { + put("key", "foo"); + put("value", "bar"); + } + }); + add(new HashMap<>()); + } + }; + + String expectedQueryString = "objects%5B0%5D%5Bvalue%5D=world&objects%5B0%5D%5Bkey%5D=hello&objects%5B1%5D" + + "%5Bvalue%5D=bar&objects%5B1%5D%5Bkey%5D=foo"; + + String actualQueryString = queryString( + new HashMap() { + { + put("objects", mapArray); + } + }, + false); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + @Test + public void testObjectArray_arraysAsRepeats() { + List> mapArray = new ArrayList>() { + { + add(new HashMap() { + { + put("key", "hello"); + put("value", "world"); + } + }); + add(new HashMap() { + { + put("key", "foo"); + put("value", "bar"); + } + }); + add(new HashMap<>()); + } + }; + + String expectedQueryString = + "objects%5Bvalue%5D=world&objects%5Bkey%5D=hello&objects%5Bvalue" + "%5D=bar&objects%5Bkey%5D=foo"; + + String actualQueryString = queryString( + new HashMap() { + { + put("objects", mapArray); + } + }, + true); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + @Test + public void testObjectWithArray_indexedArrays() { + Map objectWithArray = new HashMap() { + { + put("id", "abc123"); + put("contactIds", new ArrayList() { + { + add("id1"); + add("id2"); + add("id3"); + } + }); + } + }; + + String expectedQueryString = + "objectwitharray%5Bid%5D=abc123&objectwitharray%5BcontactIds%5D%5B0%5D=id1&objectwitharray" + + "%5BcontactIds%5D%5B1%5D=id2&objectwitharray%5BcontactIds%5D%5B2%5D=id3"; + + String actualQueryString = queryString( + new HashMap() { + { + put("objectwitharray", objectWithArray); + } + }, + false); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + @Test + public void testObjectWithArray_arraysAsRepeats() { + Map objectWithArray = new HashMap() { + { + put("id", "abc123"); + put("contactIds", new ArrayList() { + { + add("id1"); + add("id2"); + add("id3"); + } + }); + } + }; + + String expectedQueryString = "objectwitharray%5Bid%5D=abc123&objectwitharray%5BcontactIds" + + "%5D=id1&objectwitharray%5BcontactIds%5D=id2&objectwitharray%5BcontactIds%5D=id3"; + + String actualQueryString = queryString( + new HashMap() { + { + put("objectwitharray", objectWithArray); + } + }, + true); + + Assertions.assertEquals(expectedQueryString, actualQueryString); + } + + private static String queryString(Map params, boolean arraysAsRepeats) { + HttpUrl.Builder httpUrl = HttpUrl.parse("http://www.fakewebsite.com/").newBuilder(); + params.forEach((paramName, paramValue) -> + QueryStringMapper.addQueryParameter(httpUrl, paramName, paramValue, arraysAsRepeats)); + return httpUrl.build().encodedQuery(); + } +} diff --git a/seed/swift-sdk/oauth-client-credentials-with-variables/Tests/Snippets/Example4.swift b/seed/swift-sdk/oauth-client-credentials-with-variables/Tests/Snippets/Example4.swift index a562b70a7daa..af7576eb14ae 100644 --- a/seed/swift-sdk/oauth-client-credentials-with-variables/Tests/Snippets/Example4.swift +++ b/seed/swift-sdk/oauth-client-credentials-with-variables/Tests/Snippets/Example4.swift @@ -5,6 +5,6 @@ enum Example4 { static func snippet() async throws { let client = OauthClientCredentialsWithVariablesClient(baseURL: "https://api.fern.com") - _ = try await client.service.post() + _ = try await client.service.post(endpointParam: "") } } diff --git a/seed/swift-sdk/oauth-client-credentials-with-variables/reference.md b/seed/swift-sdk/oauth-client-credentials-with-variables/reference.md index 41ad40f4dfd9..f953bc2427f4 100644 --- a/seed/swift-sdk/oauth-client-credentials-with-variables/reference.md +++ b/seed/swift-sdk/oauth-client-credentials-with-variables/reference.md @@ -246,7 +246,7 @@ import OauthClientCredentialsWithVariables private func main() async throws { let client = OauthClientCredentialsWithVariablesClient() - _ = try await client.service.post() + _ = try await client.service.post(endpointParam: "") } try await main() diff --git a/seed/swift-sdk/seed.yml b/seed/swift-sdk/seed.yml index 9a9af31de632..7b6781331fd5 100644 --- a/seed/swift-sdk/seed.yml +++ b/seed/swift-sdk/seed.yml @@ -134,11 +134,9 @@ allowedFailures: - multi-url-environment - multi-url-environment-no-default - multi-url-environment-reference - - oauth-client-credentials-with-variables - query-parameters - request-parameters - trace - undiscriminated-unions # Server URL templating not yet supported in Swift SDK - server-url-templating - - variables diff --git a/seed/swift-sdk/variables/README.md b/seed/swift-sdk/variables/README.md index 4081eb3c489e..188ca4d8b485 100644 --- a/seed/swift-sdk/variables/README.md +++ b/seed/swift-sdk/variables/README.md @@ -53,7 +53,7 @@ import Variables private func main() async throws { let client = VariablesClient() - _ = try await client.service.post() + _ = try await client.service.post(endpointParam: "") } try await main() diff --git a/seed/swift-sdk/variables/Tests/Core/ClientErrorTests.swift b/seed/swift-sdk/variables/Tests/Core/ClientErrorTests.swift index febd1563245a..4ee10310f989 100644 --- a/seed/swift-sdk/variables/Tests/Core/ClientErrorTests.swift +++ b/seed/swift-sdk/variables/Tests/Core/ClientErrorTests.swift @@ -19,7 +19,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) Issue.record("Expected error to be thrown") } catch let error as VariablesError { @@ -49,7 +52,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) Issue.record("Expected error to be thrown") } catch let error as VariablesError { @@ -79,7 +85,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) Issue.record("Expected error to be thrown") } catch let error as VariablesError { @@ -111,7 +120,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) Issue.record("Expected error to be thrown") } catch let error as VariablesError { @@ -141,7 +153,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) Issue.record("Expected error to be thrown") } catch let error as VariablesError { @@ -173,7 +188,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) Issue.record("Expected error to be thrown") } catch let error as VariablesError { @@ -203,7 +221,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) Issue.record("Expected error to be thrown") } catch let error as VariablesError { diff --git a/seed/swift-sdk/variables/Tests/Core/ClientRetryTests.swift b/seed/swift-sdk/variables/Tests/Core/ClientRetryTests.swift index b47b80341730..cc47b8cd0df8 100644 --- a/seed/swift-sdk/variables/Tests/Core/ClientRetryTests.swift +++ b/seed/swift-sdk/variables/Tests/Core/ClientRetryTests.swift @@ -20,7 +20,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) } catch { } @@ -44,7 +47,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) } catch { } @@ -68,7 +74,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) } catch { } @@ -91,7 +100,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) } catch { } @@ -113,7 +125,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) Issue.record("Expected error to be thrown") } catch { @@ -136,7 +151,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) Issue.record("Expected error to be thrown") } catch { @@ -159,7 +177,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) Issue.record("Expected error to be thrown") } catch { @@ -187,7 +208,10 @@ import Testing let startTime = Date() do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) } catch { } @@ -225,7 +249,10 @@ import Testing let startTime = Date() do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) } catch { } @@ -259,7 +286,10 @@ import Testing let startTime = Date() do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) } catch { } @@ -304,7 +334,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(maxRetries: 5, additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(maxRetries: 5, additionalHeaders: stub.headers) + ) } catch { } @@ -323,7 +356,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(maxRetries: 0, additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(maxRetries: 0, additionalHeaders: stub.headers) + ) Issue.record("Expected error to be thrown") } catch { @@ -346,7 +382,10 @@ import Testing ) do { - _ = try await client.service.post(requestOptions: RequestOptions(additionalHeaders: stub.headers)) + _ = try await client.service.post( + endpointParam: "", + requestOptions: RequestOptions(additionalHeaders: stub.headers) + ) } catch { } diff --git a/seed/swift-sdk/variables/Tests/Snippets/Example0.swift b/seed/swift-sdk/variables/Tests/Snippets/Example0.swift index 986dbc24fed4..55f909e2c219 100644 --- a/seed/swift-sdk/variables/Tests/Snippets/Example0.swift +++ b/seed/swift-sdk/variables/Tests/Snippets/Example0.swift @@ -5,6 +5,6 @@ enum Example0 { static func snippet() async throws { let client = VariablesClient(baseURL: "https://api.fern.com") - _ = try await client.service.post() + _ = try await client.service.post(endpointParam: "") } } diff --git a/seed/swift-sdk/variables/Tests/Snippets/Example1.swift b/seed/swift-sdk/variables/Tests/Snippets/Example1.swift index 010b1c0f886d..a97785922dee 100644 --- a/seed/swift-sdk/variables/Tests/Snippets/Example1.swift +++ b/seed/swift-sdk/variables/Tests/Snippets/Example1.swift @@ -5,6 +5,6 @@ enum Example1 { static func snippet() async throws { let client = VariablesClient(baseURL: "https://api.fern.com") - _ = try await client.service.post() + _ = try await client.service.post(endpointParam: "") } } diff --git a/seed/swift-sdk/variables/reference.md b/seed/swift-sdk/variables/reference.md index f4c9bdeda653..975cbe3dc114 100644 --- a/seed/swift-sdk/variables/reference.md +++ b/seed/swift-sdk/variables/reference.md @@ -19,7 +19,7 @@ import Variables private func main() async throws { let client = VariablesClient() - _ = try await client.service.post() + _ = try await client.service.post(endpointParam: "") } try await main()