From c37eb4e218f31f2cb999d98db9720fd0e51e6eb5 Mon Sep 17 00:00:00 2001 From: hyochan Date: Wed, 17 Sep 2025 02:43:42 +0900 Subject: [PATCH] feat(generated): align cross-lang types --- scripts/fix-generated-types.mjs | 21 + scripts/generate-dart-types.mjs | 268 ++++- scripts/generate-kotlin-types.mjs | 250 ++++- src/generated/Types.kt | 1395 +++++++++++++++++++++++-- src/generated/Types.swift | 32 +- src/generated/types.dart | 1610 +++++++++++++++++++++++++++-- src/generated/types.ts | 82 +- src/type-android.graphql | 8 +- src/type-ios.graphql | 6 +- src/type.graphql | 14 +- 10 files changed, 3336 insertions(+), 350 deletions(-) diff --git a/scripts/fix-generated-types.mjs b/scripts/fix-generated-types.mjs index 01c6798..6ba023e 100644 --- a/scripts/fix-generated-types.mjs +++ b/scripts/fix-generated-types.mjs @@ -64,6 +64,27 @@ for (const [tsName, iosName] of iosTypeMap) { content = content.replace(pattern, iosName); } +// Enforce IOS capitalization conventions for enum members and fields. +content = content.replace(/\b([A-Za-z0-9]+)Ios\b/g, (_, prefix) => `${prefix}IOS`); +content = content.replace(/\bIos\b/g, 'IOS'); + +const toKebabCase = (value) => value + .replace(/([a-z0-9])([A-Z])/g, '$1-$2') + .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2') + .replace(/[_\s]+/g, '-') + .replace(/-+/g, '-') + .toLowerCase(); + +// Convert enums (except ErrorCode) to union literal types with lower-snake-case values. +content = content.replace(/export enum (\w+) \{[\s\S]*?\}\n?/g, (match) => { + const enumName = match.match(/export enum (\w+)/)[1]; + if (enumName === 'ErrorCode') return match; + const valueMatches = [...match.matchAll(/=\s*'([^']+)'/g)]; + if (valueMatches.length === 0) return match; + const literals = valueMatches.map(([, raw]) => `'${toKebabCase(raw)}'`); + return `export type ${enumName} = ${literals.join(' | ')};\n`; +}); + const removeDefinition = (keyword) => { const pattern = new RegExp(`^export type ${keyword}[^]*?;\n`, 'm'); if (pattern.test(content)) { diff --git a/scripts/generate-dart-types.mjs b/scripts/generate-dart-types.mjs index b554420..c6c6c08 100644 --- a/scripts/generate-dart-types.mjs +++ b/scripts/generate-dart-types.mjs @@ -72,9 +72,17 @@ const toCamelCase = (value, upper = false) => { .filter(Boolean) .map((token) => token.toLowerCase()); if (tokens.length === 0) return value; - const [first, ...rest] = tokens; - const firstToken = upper ? first.charAt(0).toUpperCase() + first.slice(1) : first; - return [firstToken, ...rest.map((token) => token.charAt(0).toUpperCase() + token.slice(1))].join(''); + const normalized = tokens.map((token) => (token === 'ios' ? 'IOS' : token)); + const [first, ...rest] = normalized; + const formatFirst = () => { + if (first === 'IOS') { + return upper ? 'IOS' : 'ios'; + } + return upper ? first.charAt(0).toUpperCase() + first.slice(1) : first; + }; + const firstToken = formatFirst(); + const restTokens = rest.map((token) => (token === 'IOS' ? 'IOS' : token.charAt(0).toUpperCase() + token.slice(1))); + return [firstToken, ...restTokens].join(''); }; const toPascalCase = (value) => toCamelCase(value, true); @@ -93,20 +101,6 @@ const scalarMap = new Map([ ['Float', 'double'], ]); -const getDartType = (graphqlType) => { - if (graphqlType instanceof GraphQLNonNull) { - const inner = getDartType(graphqlType.ofType); - return { type: inner.type, nullable: false }; - } - if (graphqlType instanceof GraphQLList) { - const inner = getDartType(graphqlType.ofType); - const element = inner.type + (inner.nullable ? '?' : ''); - return { type: `List<${element}>`, nullable: true }; - } - const mapped = scalarMap.get(graphqlType.name) ?? graphqlType.name; - return { type: mapped, nullable: true }; -}; - const addDocComment = (lines, description, indent = '') => { if (!description) return; for (const docLine of description.split(/\r?\n/)) { @@ -154,11 +148,128 @@ for (const name of typeNames) { objects.push(type); continue; } - if (isInputObjectType(type)) { +if (isInputObjectType(type)) { inputs.push(type); } } +const enumNames = new Set(enums.map((value) => value.name)); +const interfaceNames = new Set(interfaces.map((value) => value.name)); +const objectNames = new Set(objects.map((value) => value.name)); +const inputNames = new Set(inputs.map((value) => value.name)); +const unionNames = new Set(unions.map((value) => value.name)); + +const getTypeMetadata = (graphqlType) => { + if (graphqlType instanceof GraphQLNonNull) { + const inner = getTypeMetadata(graphqlType.ofType); + return { ...inner, nullable: false }; + } + if (graphqlType instanceof GraphQLList) { + const inner = getTypeMetadata(graphqlType.ofType); + const innerType = inner.dartType + (inner.nullable ? '?' : ''); + return { + kind: 'list', + nullable: true, + elementType: inner, + dartType: `List<${innerType}>`, + }; + } + const typeName = graphqlType.name; + let kind = 'object'; + if (scalarMap.has(typeName)) { + kind = 'scalar'; + } else if (enumNames.has(typeName)) { + kind = 'enum'; + } else if (interfaceNames.has(typeName)) { + kind = 'interface'; + } else if (inputNames.has(typeName)) { + kind = 'input'; + } else if (unionNames.has(typeName)) { + kind = 'union'; + } else if (objectNames.has(typeName)) { + kind = 'object'; + } + const dartType = scalarMap.get(typeName) ?? typeName; + return { + kind, + name: typeName, + nullable: true, + dartType, + }; +}; + +const getDartType = (graphqlType) => { + const metadata = getTypeMetadata(graphqlType); + return { type: metadata.dartType, nullable: metadata.nullable, metadata }; +}; + +const buildFromJsonExpression = (metadata, sourceExpression) => { + if (metadata.kind === 'list') { + const listCast = `(${sourceExpression} as List${metadata.nullable ? '?' : ''})`; + const elementExpression = buildFromJsonExpression(metadata.elementType, 'e'); + const mapCall = (target) => `${target}.map((e) => ${elementExpression}).toList()`; + if (metadata.nullable) { + return `${listCast} == null ? null : ${mapCall(`${listCast}!`)}`; + } + return mapCall(listCast); + } + if (metadata.kind === 'scalar') { + switch (metadata.name) { + case 'Float': + return metadata.nullable + ? `(${sourceExpression} as num?)?.toDouble()` + : `(${sourceExpression} as num).toDouble()`; + case 'Int': + return metadata.nullable + ? `${sourceExpression} as int?` + : `${sourceExpression} as int`; + case 'Boolean': + return metadata.nullable + ? `${sourceExpression} as bool?` + : `${sourceExpression} as bool`; + case 'ID': + case 'String': + return metadata.nullable + ? `${sourceExpression} as String?` + : `${sourceExpression} as String`; + default: + return metadata.nullable ? `${sourceExpression}` : `${sourceExpression}`; + } + } + if (metadata.kind === 'enum') { + return metadata.nullable + ? `${sourceExpression} != null ? ${metadata.name}.fromJson(${sourceExpression} as String) : null` + : `${metadata.name}.fromJson(${sourceExpression} as String)`; + } + if (['object', 'input', 'interface', 'union'].includes(metadata.kind)) { + return metadata.nullable + ? `${sourceExpression} != null ? ${metadata.dartType}.fromJson(${sourceExpression} as Map) : null` + : `${metadata.dartType}.fromJson(${sourceExpression} as Map)`; + } + return metadata.nullable ? `${sourceExpression}` : `${sourceExpression}`; +}; + +const buildToJsonExpression = (metadata, accessorExpression) => { + if (metadata.kind === 'list') { + const inner = buildToJsonExpression(metadata.elementType, 'e'); + if (metadata.nullable) { + return `${accessorExpression} == null ? null : ${accessorExpression}!.map((e) => ${inner}).toList()`; + } + return `${accessorExpression}.map((e) => ${inner}).toList()`; + } + if (metadata.kind === 'enum') { + return metadata.nullable + ? `${accessorExpression}?.toJson()` + : `${accessorExpression}.toJson()`; + } + if (['object', 'input', 'interface', 'union'].includes(metadata.kind)) { + return metadata.nullable + ? `${accessorExpression}?.toJson()` + : `${accessorExpression}.toJson()`; + } + return accessorExpression; +}; + const lines = []; lines.push( '// ============================================================================', @@ -178,12 +289,37 @@ const printEnum = (enumType) => { const values = enumType.getValues(); values.forEach((value, index) => { addDocComment(lines, value.description, ' '); - const name = escapeDartName(toCamelCase(value.name)); + const name = escapeDartName(toPascalCase(value.name)); const rawValue = toConstantCase(value.name); const suffix = index === values.length - 1 ? ';' : ','; lines.push(` ${name}('${rawValue}')${suffix}`); }); - lines.push('', ` const ${enumType.name}(this.value);`, ' final String value;', '}', ''); + lines.push( + '', + ` const ${enumType.name}(this.value);`, + ' final String value;', + '', + ` factory ${enumType.name}.fromJson(String value) {`, + ' switch (value) {' + ); + values.forEach((value) => { + const name = escapeDartName(toPascalCase(value.name)); + const rawValue = toConstantCase(value.name); + const schemaValue = value.name; + lines.push(` case '${rawValue}':`, ` return ${enumType.name}.${name};`); + if (schemaValue !== rawValue) { + lines.push(` case '${schemaValue}':`, ` return ${enumType.name}.${name};`); + } + }); + lines.push( + ' }', + ` throw ArgumentError('Unknown ${enumType.name} value: $value');`, + ' }', + '', + ' String toJson() => value;', + '}', + '' + ); }; const printInterface = (interfaceType) => { @@ -203,30 +339,53 @@ const printInterface = (interfaceType) => { const printObject = (objectType) => { addDocComment(lines, objectType.description); const interfacesForObject = objectType.getInterfaces().map((iface) => iface.name); - const unionInterfaces = unionMembership.has(objectType.name) + const unionsForObject = unionMembership.has(objectType.name) ? Array.from(unionMembership.get(objectType.name)).sort() : []; - const implementsList = [...interfacesForObject, ...unionInterfaces]; - const implementsClause = implementsList.length ? ` implements ${implementsList.join(', ')}` : ''; - lines.push(`class ${objectType.name}${implementsClause} {`); + const baseUnion = unionsForObject.shift() ?? null; + const extendsClause = baseUnion ? ` extends ${baseUnion}` : ''; + const implementsTargets = [...interfacesForObject, ...unionsForObject]; + const implementsClause = implementsTargets.length ? ` implements ${implementsTargets.join(', ')}` : ''; + lines.push(`class ${objectType.name}${extendsClause}${implementsClause} {`); lines.push(` const ${objectType.name}({`); const fields = Object.values(objectType.getFields()).sort((a, b) => a.name.localeCompare(b.name)); - fields.forEach((field, index) => { - addDocComment(lines, field.description, ' '); - const { type, nullable } = getDartType(field.type); - const fieldType = `${type}${nullable ? '?' : ''}`; + const fieldInfos = fields.map((field) => { + const { type, nullable, metadata } = getDartType(field.type); const fieldName = escapeDartName(field.name); + return { field, fieldName, type, nullable, metadata }; + }); + fieldInfos.forEach(({ field, nullable, fieldName }) => { + addDocComment(lines, field.description, ' '); const line = ` ${nullable ? '' : 'required '}this.${fieldName},`; lines.push(line); }); lines.push(' });', ''); - fields.forEach((field) => { + fieldInfos.forEach(({ field, type, nullable, fieldName }) => { addDocComment(lines, field.description, ' '); - const { type, nullable } = getDartType(field.type); const fieldType = `${type}${nullable ? '?' : ''}`; - const fieldName = escapeDartName(field.name); lines.push(` final ${fieldType} ${fieldName};`); }); + lines.push(''); + lines.push(` factory ${objectType.name}.fromJson(Map json) {`); + lines.push(` return ${objectType.name}(`); + fieldInfos.forEach(({ field, fieldName, metadata }) => { + const jsonExpression = buildFromJsonExpression(metadata, `json['${field.name}']`); + lines.push(` ${fieldName}: ${jsonExpression},`); + }); + lines.push(' );'); + lines.push(' }', ''); + if (baseUnion) { + lines.push(' @override'); + } + lines.push(' Map toJson() {'); + lines.push(' return {'); + lines.push(` '__typename': '${objectType.name}',`); + fieldInfos.forEach(({ field, fieldName, metadata }) => { + const toJsonExpression = buildToJsonExpression(metadata, fieldName); + lines.push(` '${field.name}': ${toJsonExpression},`); + }); + lines.push(' };'); + lines.push(' }'); lines.push('}', ''); }; @@ -235,29 +394,58 @@ const printInput = (inputType) => { lines.push(`class ${inputType.name} {`); lines.push(` const ${inputType.name}({`); const fields = Object.values(inputType.getFields()).sort((a, b) => a.name.localeCompare(b.name)); - fields.forEach((field) => { - addDocComment(lines, field.description, ' '); - const { type, nullable } = getDartType(field.type); - const fieldType = `${type}${nullable ? '?' : ''}`; + const fieldInfos = fields.map((field) => { + const { type, nullable, metadata } = getDartType(field.type); const fieldName = escapeDartName(field.name); + return { field, fieldName, type, nullable, metadata }; + }); + fieldInfos.forEach(({ field, nullable, fieldName }) => { + addDocComment(lines, field.description, ' '); const line = ` ${nullable ? '' : 'required '}this.${fieldName},`; lines.push(line); }); lines.push(' });', ''); - fields.forEach((field) => { + fieldInfos.forEach(({ field, type, nullable, fieldName }) => { addDocComment(lines, field.description, ' '); - const { type, nullable } = getDartType(field.type); const fieldType = `${type}${nullable ? '?' : ''}`; - const fieldName = escapeDartName(field.name); lines.push(` final ${fieldType} ${fieldName};`); }); + lines.push(''); + lines.push(` factory ${inputType.name}.fromJson(Map json) {`); + lines.push(` return ${inputType.name}(`); + fieldInfos.forEach(({ field, fieldName, metadata }) => { + const jsonExpression = buildFromJsonExpression(metadata, `json['${field.name}']`); + lines.push(` ${fieldName}: ${jsonExpression},`); + }); + lines.push(' );'); + lines.push(' }', ''); + lines.push(' Map toJson() {'); + lines.push(' return {'); + fieldInfos.forEach(({ field, fieldName, metadata }) => { + const toJsonExpression = buildToJsonExpression(metadata, fieldName); + lines.push(` '${field.name}': ${toJsonExpression},`); + }); + lines.push(' };'); + lines.push(' }'); lines.push('}', ''); }; const printUnion = (unionType) => { addDocComment(lines, unionType.description); - lines.push(`abstract class ${unionType.name} {}`); - lines.push(''); + const members = unionType.getTypes().map((member) => member.name).sort(); + lines.push(`sealed class ${unionType.name} {`); + lines.push(` const ${unionType.name}();`, ''); + lines.push(` factory ${unionType.name}.fromJson(Map json) {`); + lines.push(` final typeName = json['__typename'] as String?;`); + lines.push(' switch (typeName) {'); + members.forEach((member) => { + lines.push(` case '${member}':`, ` return ${member}.fromJson(json);`); + }); + lines.push(' }'); + lines.push(` throw ArgumentError('Unknown __typename for ${unionType.name}: $typeName');`); + lines.push(' }', ''); + lines.push(' Map toJson();'); + lines.push('}', ''); }; const printOperationInterface = (operationType) => { diff --git a/scripts/generate-kotlin-types.mjs b/scripts/generate-kotlin-types.mjs index 0c01d47..2c3306f 100644 --- a/scripts/generate-kotlin-types.mjs +++ b/scripts/generate-kotlin-types.mjs @@ -102,19 +102,11 @@ const scalarMap = new Map([ ['Float', 'Double'], ]); -const getKotlinType = (graphqlType) => { - if (graphqlType instanceof GraphQLNonNull) { - const inner = getKotlinType(graphqlType.ofType); - return { type: inner.type, nullable: false }; - } - if (graphqlType instanceof GraphQLList) { - const inner = getKotlinType(graphqlType.ofType); - const innerType = inner.type + (inner.nullable ? '?' : ''); - return { type: `List<${innerType}>`, nullable: true }; - } - const mapped = scalarMap.get(graphqlType.name) ?? graphqlType.name; - return { type: mapped, nullable: true }; -}; +const enumNames = new Set(); +const interfaceNames = new Set(); +const objectNames = new Set(); +const inputNames = new Set(); +const unionNames = new Set(); const addDocComment = (lines, description, indent = '') => { if (!description) return; @@ -170,6 +162,131 @@ for (const name of typeNames) { } } +for (const enumType of enums) { + enumNames.add(enumType.name); +} +for (const interfaceType of interfaces) { + interfaceNames.add(interfaceType.name); +} +for (const objectType of objects) { + objectNames.add(objectType.name); +} +for (const inputType of inputs) { + inputNames.add(inputType.name); +} +for (const unionType of unions) { + unionNames.add(unionType.name); +} + +const getTypeMetadata = (graphqlType) => { + if (graphqlType instanceof GraphQLNonNull) { + const inner = getTypeMetadata(graphqlType.ofType); + return { ...inner, nullable: false }; + } + if (graphqlType instanceof GraphQLList) { + const inner = getTypeMetadata(graphqlType.ofType); + const elementType = { ...inner }; + const elementKotlin = inner.kotlinType + (inner.nullable ? '?' : ''); + return { + kind: 'list', + nullable: true, + elementType, + kotlinType: `List<${elementKotlin}>`, + }; + } + const typeName = graphqlType.name; + let kind = 'object'; + if (scalarMap.has(typeName)) { + kind = 'scalar'; + } else if (enumNames.has(typeName)) { + kind = 'enum'; + } else if (interfaceNames.has(typeName)) { + kind = 'interface'; + } else if (inputNames.has(typeName)) { + kind = 'input'; + } else if (unionNames.has(typeName)) { + kind = 'union'; + } else if (objectNames.has(typeName)) { + kind = 'object'; + } + const kotlinType = scalarMap.get(typeName) ?? typeName; + return { + kind, + name: typeName, + nullable: true, + kotlinType, + }; +}; + +const getKotlinType = (graphqlType) => { + const metadata = getTypeMetadata(graphqlType); + return { type: metadata.kotlinType, nullable: metadata.nullable, metadata }; +}; + +const buildFromJsonExpression = (metadata, sourceExpression) => { + if (metadata.kind === 'list') { + const element = buildFromJsonExpression(metadata.elementType, 'it'); + if (metadata.nullable) { + return `(${sourceExpression} as List<*>?)?.map { ${element} }`; + } + return `(${sourceExpression} as List<*>).map { ${element} }`; + } + if (metadata.kind === 'scalar') { + switch (metadata.name) { + case 'Float': + return metadata.nullable + ? `(${sourceExpression} as Number?)?.toDouble()` + : `(${sourceExpression} as Number).toDouble()`; + case 'Int': + return metadata.nullable + ? `(${sourceExpression} as Number?)?.toInt()` + : `(${sourceExpression} as Number).toInt()`; + case 'Boolean': + return metadata.nullable + ? `${sourceExpression} as Boolean?` + : `${sourceExpression} as Boolean`; + case 'ID': + case 'String': + return metadata.nullable + ? `${sourceExpression} as String?` + : `${sourceExpression} as String`; + default: + return metadata.nullable ? `${sourceExpression}` : `${sourceExpression}`; + } + } + if (metadata.kind === 'enum') { + return metadata.nullable + ? `(${sourceExpression} as String?)?.let { ${metadata.name}.fromJson(it) }` + : `${metadata.name}.fromJson(${sourceExpression} as String)`; + } + if (['object', 'input', 'interface', 'union'].includes(metadata.kind)) { + const cast = metadata.nullable + ? `(${sourceExpression} as Map?)` + : `(${sourceExpression} as Map)`; + const callTarget = metadata.name ?? metadata.kotlinType; + return metadata.nullable + ? `${cast}?.let { ${callTarget}.fromJson(it) }` + : `${callTarget}.fromJson(${cast})`; + } + return metadata.nullable ? `${sourceExpression}` : `${sourceExpression}`; +}; + +const buildToJsonExpression = (metadata, accessorExpression) => { + if (metadata.kind === 'list') { + const inner = buildToJsonExpression(metadata.elementType, 'it'); + return metadata.nullable + ? `${accessorExpression}?.map { ${inner} }` + : `${accessorExpression}.map { ${inner} }`; + } + if (metadata.kind === 'enum') { + return metadata.nullable ? `${accessorExpression}?.toJson()` : `${accessorExpression}.toJson()`; + } + if (['object', 'input', 'interface', 'union'].includes(metadata.kind)) { + return metadata.nullable ? `${accessorExpression}?.toJson()` : `${accessorExpression}.toJson()`; + } + return accessorExpression; +}; + const lines = []; lines.push( '// ============================================================================', @@ -192,6 +309,16 @@ const printEnum = (enumType) => { const suffix = index === values.length - 1 ? '' : ','; lines.push(` ${caseName}("${rawValue}")${suffix}`); }); + lines.push('', ' companion object {'); + lines.push(` fun fromJson(value: String): ${enumType.name} = when (value) {`); + values.forEach((value) => { + const caseName = escapeKotlinName(pascalCase(value.name)); + const rawValue = toConstantCase(value.name); + lines.push(` "${rawValue}" -> ${enumType.name}.${caseName}`); + }); + lines.push(` else -> throw IllegalArgumentException("Unknown ${enumType.name} value: $value")`, ' }'); + lines.push(' }', ''); + lines.push(' fun toJson(): String = rawValue'); lines.push('}', ''); }; @@ -215,54 +342,105 @@ const printDataClass = (objectType) => { const unionInterfaces = unionMembership.has(objectType.name) ? Array.from(unionMembership.get(objectType.name)).sort() : []; - const conformances = ['public data class', `${objectType.name}(`]; const fields = Object.values(objectType.getFields()).sort((a, b) => a.name.localeCompare(b.name)); - const propertyLines = []; - fields.forEach((field, index) => { - const { type, nullable } = getKotlinType(field.type); - const propertyType = type + (nullable ? '?' : ''); - const propertyName = escapeKotlinName(field.name); - const defaultValue = nullable ? ' = null' : ''; - addDocComment(propertyLines, field.description, ' '); - const suffix = index === fields.length - 1 ? '' : ','; - propertyLines.push(` val ${propertyName}: ${propertyType}${defaultValue}${suffix}`); - }); if (fields.length === 0) { lines.push(`public class ${objectType.name}`); lines.push(''); return; } - lines.push(`${conformances[0]} ${conformances[1]}`); - lines.push(...propertyLines); + const fieldInfos = fields.map((field) => { + const { type, nullable, metadata } = getKotlinType(field.type); + const propertyType = type + (nullable ? '?' : ''); + const propertyName = escapeKotlinName(field.name); + const defaultValue = nullable ? ' = null' : ''; + return { field, propertyName, propertyType, defaultValue, metadata }; + }); + lines.push(`public data class ${objectType.name}(`); + fieldInfos.forEach(({ field, propertyName, propertyType, defaultValue }, index) => { + addDocComment(lines, field.description, ' '); + const suffix = index === fieldInfos.length - 1 ? '' : ','; + lines.push(` val ${propertyName}: ${propertyType}${defaultValue}${suffix}`); + }); const implementsList = [...interfacesForObject, ...unionInterfaces]; if (implementsList.length > 0) { - lines.push(`) : ${implementsList.join(', ')}`); + lines.push(`) : ${implementsList.join(', ')} {`); } else { - lines.push(')'); + lines.push(') {'); } - lines.push('', ''); + lines.push(''); + lines.push(' companion object {'); + lines.push(` fun fromJson(json: Map): ${objectType.name} {`); + lines.push(` return ${objectType.name}(`); + fieldInfos.forEach(({ field, propertyName, metadata }) => { + const expression = buildFromJsonExpression(metadata, `json["${field.name}"]`); + lines.push(` ${propertyName} = ${expression},`); + }); + lines.push(' )'); + lines.push(' }'); + lines.push(' }', ''); + const overrideKeyword = unionInterfaces.length > 0 ? 'override ' : ''; + lines.push(` ${overrideKeyword}fun toJson(): Map = mapOf(`); + lines.push(` "__typename" to "${objectType.name}",`); + fieldInfos.forEach(({ field, propertyName, metadata }) => { + const expression = buildToJsonExpression(metadata, propertyName); + lines.push(` "${field.name}" to ${expression},`); + }); + lines.push(' )'); + lines.push('}', ''); }; const printInput = (inputType) => { addDocComment(lines, inputType.description); const fields = Object.values(inputType.getFields()).sort((a, b) => a.name.localeCompare(b.name)); - lines.push(`public data class ${inputType.name}(`); - fields.forEach((field, index) => { - const { type, nullable } = getKotlinType(field.type); + const fieldInfos = fields.map((field) => { + const { type, nullable, metadata } = getKotlinType(field.type); const propertyType = type + (nullable ? '?' : ''); const propertyName = escapeKotlinName(field.name); const defaultValue = nullable ? ' = null' : ''; + return { field, propertyName, propertyType, defaultValue, metadata }; + }); + lines.push(`public data class ${inputType.name}(`); + fieldInfos.forEach(({ field, propertyName, propertyType, defaultValue }, index) => { addDocComment(lines, field.description, ' '); - const suffix = index === fields.length - 1 ? '' : ','; + const suffix = index === fieldInfos.length - 1 ? '' : ','; lines.push(` val ${propertyName}: ${propertyType}${defaultValue}${suffix}`); }); - lines.push(')', ''); + lines.push(') {'); + lines.push(' companion object {'); + lines.push(` fun fromJson(json: Map): ${inputType.name} {`); + lines.push(` return ${inputType.name}(`); + fieldInfos.forEach(({ field, propertyName, metadata }) => { + const expression = buildFromJsonExpression(metadata, `json["${field.name}"]`); + lines.push(` ${propertyName} = ${expression},`); + }); + lines.push(' )'); + lines.push(' }'); + lines.push(' }', ''); + lines.push(' fun toJson(): Map = mapOf('); + fieldInfos.forEach(({ field, propertyName, metadata }) => { + const expression = buildToJsonExpression(metadata, propertyName); + lines.push(` "${field.name}" to ${expression},`); + }); + lines.push(' )'); + lines.push('}', ''); }; const printUnion = (unionType) => { addDocComment(lines, unionType.description); - lines.push(`public sealed interface ${unionType.name}`); - lines.push(''); + const members = unionType.getTypes().map((member) => member.name).sort(); + lines.push(`public sealed interface ${unionType.name} {`); + lines.push(' fun toJson(): Map', ''); + lines.push(' companion object {'); + lines.push(` fun fromJson(json: Map): ${unionType.name} {`); + lines.push(' return when (json["__typename"] as String?) {'); + members.forEach((member) => { + lines.push(` "${member}" -> ${member}.fromJson(json)`); + }); + lines.push(` else -> throw IllegalArgumentException("Unknown __typename for ${unionType.name}: ${'$'}{json["__typename"]}")`); + lines.push(' }'); + lines.push(' }'); + lines.push(' }'); + lines.push('}', ''); }; const printOperationInterface = (operationType) => { diff --git a/src/generated/Types.kt b/src/generated/Types.kt index ca32f9a..ff02f37 100644 --- a/src/generated/Types.kt +++ b/src/generated/Types.kt @@ -42,12 +42,80 @@ public enum class ErrorCode(val rawValue: String) { BillingUnavailable("BILLING_UNAVAILABLE"), FeatureNotSupported("FEATURE_NOT_SUPPORTED"), EmptySkuList("EMPTY_SKU_LIST") + + companion object { + fun fromJson(value: String): ErrorCode = when (value) { + "UNKNOWN" -> ErrorCode.Unknown + "USER_CANCELLED" -> ErrorCode.UserCancelled + "USER_ERROR" -> ErrorCode.UserError + "ITEM_UNAVAILABLE" -> ErrorCode.ItemUnavailable + "REMOTE_ERROR" -> ErrorCode.RemoteError + "NETWORK_ERROR" -> ErrorCode.NetworkError + "SERVICE_ERROR" -> ErrorCode.ServiceError + "RECEIPT_FAILED" -> ErrorCode.ReceiptFailed + "RECEIPT_FINISHED" -> ErrorCode.ReceiptFinished + "RECEIPT_FINISHED_FAILED" -> ErrorCode.ReceiptFinishedFailed + "NOT_PREPARED" -> ErrorCode.NotPrepared + "NOT_ENDED" -> ErrorCode.NotEnded + "ALREADY_OWNED" -> ErrorCode.AlreadyOwned + "DEVELOPER_ERROR" -> ErrorCode.DeveloperError + "BILLING_RESPONSE_JSON_PARSE_ERROR" -> ErrorCode.BillingResponseJsonParseError + "DEFERRED_PAYMENT" -> ErrorCode.DeferredPayment + "INTERRUPTED" -> ErrorCode.Interrupted + "IAP_NOT_AVAILABLE" -> ErrorCode.IapNotAvailable + "PURCHASE_ERROR" -> ErrorCode.PurchaseError + "SYNC_ERROR" -> ErrorCode.SyncError + "TRANSACTION_VALIDATION_FAILED" -> ErrorCode.TransactionValidationFailed + "ACTIVITY_UNAVAILABLE" -> ErrorCode.ActivityUnavailable + "ALREADY_PREPARED" -> ErrorCode.AlreadyPrepared + "PENDING" -> ErrorCode.Pending + "CONNECTION_CLOSED" -> ErrorCode.ConnectionClosed + "INIT_CONNECTION" -> ErrorCode.InitConnection + "SERVICE_DISCONNECTED" -> ErrorCode.ServiceDisconnected + "QUERY_PRODUCT" -> ErrorCode.QueryProduct + "SKU_NOT_FOUND" -> ErrorCode.SkuNotFound + "SKU_OFFER_MISMATCH" -> ErrorCode.SkuOfferMismatch + "ITEM_NOT_OWNED" -> ErrorCode.ItemNotOwned + "BILLING_UNAVAILABLE" -> ErrorCode.BillingUnavailable + "FEATURE_NOT_SUPPORTED" -> ErrorCode.FeatureNotSupported + "EMPTY_SKU_LIST" -> ErrorCode.EmptySkuList + else -> throw IllegalArgumentException("Unknown ErrorCode value: $value") + } + } + + fun toJson(): String = rawValue } public enum class IapEvent(val rawValue: String) { PurchaseUpdated("PURCHASE_UPDATED"), PurchaseError("PURCHASE_ERROR"), PromotedProductIos("PROMOTED_PRODUCT_IOS") + + companion object { + fun fromJson(value: String): IapEvent = when (value) { + "PURCHASE_UPDATED" -> IapEvent.PurchaseUpdated + "PURCHASE_ERROR" -> IapEvent.PurchaseError + "PROMOTED_PRODUCT_IOS" -> IapEvent.PromotedProductIos + else -> throw IllegalArgumentException("Unknown IapEvent value: $value") + } + } + + fun toJson(): String = rawValue +} + +public enum class IapPlatform(val rawValue: String) { + Ios("IOS"), + Android("ANDROID") + + companion object { + fun fromJson(value: String): IapPlatform = when (value) { + "IOS" -> IapPlatform.Ios + "ANDROID" -> IapPlatform.Android + else -> throw IllegalArgumentException("Unknown IapPlatform value: $value") + } + } + + fun toJson(): String = rawValue } public enum class PaymentModeIOS(val rawValue: String) { @@ -55,22 +123,50 @@ public enum class PaymentModeIOS(val rawValue: String) { FreeTrial("FREE_TRIAL"), PayAsYouGo("PAY_AS_YOU_GO"), PayUpFront("PAY_UP_FRONT") -} -public enum class Platform(val rawValue: String) { - Ios("IOS"), - Android("ANDROID") + companion object { + fun fromJson(value: String): PaymentModeIOS = when (value) { + "EMPTY" -> PaymentModeIOS.Empty + "FREE_TRIAL" -> PaymentModeIOS.FreeTrial + "PAY_AS_YOU_GO" -> PaymentModeIOS.PayAsYouGo + "PAY_UP_FRONT" -> PaymentModeIOS.PayUpFront + else -> throw IllegalArgumentException("Unknown PaymentModeIOS value: $value") + } + } + + fun toJson(): String = rawValue } public enum class ProductQueryType(val rawValue: String) { InApp("IN_APP"), Subs("SUBS"), All("ALL") + + companion object { + fun fromJson(value: String): ProductQueryType = when (value) { + "IN_APP" -> ProductQueryType.InApp + "SUBS" -> ProductQueryType.Subs + "ALL" -> ProductQueryType.All + else -> throw IllegalArgumentException("Unknown ProductQueryType value: $value") + } + } + + fun toJson(): String = rawValue } public enum class ProductType(val rawValue: String) { InApp("IN_APP"), Subs("SUBS") + + companion object { + fun fromJson(value: String): ProductType = when (value) { + "IN_APP" -> ProductType.InApp + "SUBS" -> ProductType.Subs + else -> throw IllegalArgumentException("Unknown ProductType value: $value") + } + } + + fun toJson(): String = rawValue } public enum class ProductTypeIOS(val rawValue: String) { @@ -78,6 +174,18 @@ public enum class ProductTypeIOS(val rawValue: String) { NonConsumable("NON_CONSUMABLE"), AutoRenewableSubscription("AUTO_RENEWABLE_SUBSCRIPTION"), NonRenewingSubscription("NON_RENEWING_SUBSCRIPTION") + + companion object { + fun fromJson(value: String): ProductTypeIOS = when (value) { + "CONSUMABLE" -> ProductTypeIOS.Consumable + "NON_CONSUMABLE" -> ProductTypeIOS.NonConsumable + "AUTO_RENEWABLE_SUBSCRIPTION" -> ProductTypeIOS.AutoRenewableSubscription + "NON_RENEWING_SUBSCRIPTION" -> ProductTypeIOS.NonRenewingSubscription + else -> throw IllegalArgumentException("Unknown ProductTypeIOS value: $value") + } + } + + fun toJson(): String = rawValue } public enum class PurchaseState(val rawValue: String) { @@ -87,11 +195,35 @@ public enum class PurchaseState(val rawValue: String) { Restored("RESTORED"), Deferred("DEFERRED"), Unknown("UNKNOWN") + + companion object { + fun fromJson(value: String): PurchaseState = when (value) { + "PENDING" -> PurchaseState.Pending + "PURCHASED" -> PurchaseState.Purchased + "FAILED" -> PurchaseState.Failed + "RESTORED" -> PurchaseState.Restored + "DEFERRED" -> PurchaseState.Deferred + "UNKNOWN" -> PurchaseState.Unknown + else -> throw IllegalArgumentException("Unknown PurchaseState value: $value") + } + } + + fun toJson(): String = rawValue } public enum class SubscriptionOfferTypeIOS(val rawValue: String) { Introductory("INTRODUCTORY"), Promotional("PROMOTIONAL") + + companion object { + fun fromJson(value: String): SubscriptionOfferTypeIOS = when (value) { + "INTRODUCTORY" -> SubscriptionOfferTypeIOS.Introductory + "PROMOTIONAL" -> SubscriptionOfferTypeIOS.Promotional + else -> throw IllegalArgumentException("Unknown SubscriptionOfferTypeIOS value: $value") + } + } + + fun toJson(): String = rawValue } public enum class SubscriptionPeriodIOS(val rawValue: String) { @@ -100,6 +232,19 @@ public enum class SubscriptionPeriodIOS(val rawValue: String) { Month("MONTH"), Year("YEAR"), Empty("EMPTY") + + companion object { + fun fromJson(value: String): SubscriptionPeriodIOS = when (value) { + "DAY" -> SubscriptionPeriodIOS.Day + "WEEK" -> SubscriptionPeriodIOS.Week + "MONTH" -> SubscriptionPeriodIOS.Month + "YEAR" -> SubscriptionPeriodIOS.Year + "EMPTY" -> SubscriptionPeriodIOS.Empty + else -> throw IllegalArgumentException("Unknown SubscriptionPeriodIOS value: $value") + } + } + + fun toJson(): String = rawValue } // MARK: - Interfaces @@ -111,7 +256,7 @@ public interface ProductCommon { val displayName: String? val displayPrice: String val id: String - val platform: Platform + val platform: IapPlatform val price: Double? val title: String val type: ProductType @@ -121,7 +266,7 @@ public interface PurchaseCommon { val id: String val ids: List? val isAutoRenewing: Boolean - val platform: Platform + val platform: IapPlatform val productId: String val purchaseState: PurchaseState /** @@ -145,8 +290,39 @@ public data class ActiveSubscription( val transactionDate: Double, val transactionId: String, val willExpireSoon: Boolean? = null -) - +) { + + companion object { + fun fromJson(json: Map): ActiveSubscription { + return ActiveSubscription( + autoRenewingAndroid = json["autoRenewingAndroid"] as Boolean?, + daysUntilExpirationIOS = (json["daysUntilExpirationIOS"] as Number?)?.toDouble(), + environmentIOS = json["environmentIOS"] as String?, + expirationDateIOS = (json["expirationDateIOS"] as Number?)?.toDouble(), + isActive = json["isActive"] as Boolean, + productId = json["productId"] as String, + purchaseToken = json["purchaseToken"] as String?, + transactionDate = (json["transactionDate"] as Number).toDouble(), + transactionId = json["transactionId"] as String, + willExpireSoon = json["willExpireSoon"] as Boolean?, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "ActiveSubscription", + "autoRenewingAndroid" to autoRenewingAndroid, + "daysUntilExpirationIOS" to daysUntilExpirationIOS, + "environmentIOS" to environmentIOS, + "expirationDateIOS" to expirationDateIOS, + "isActive" to isActive, + "productId" to productId, + "purchaseToken" to purchaseToken, + "transactionDate" to transactionDate, + "transactionId" to transactionId, + "willExpireSoon" to willExpireSoon, + ) +} public data class AppTransaction( val appId: Double, @@ -162,8 +338,45 @@ public data class AppTransaction( val originalPurchaseDate: Double, val preorderDate: Double? = null, val signedDate: Double -) - +) { + + companion object { + fun fromJson(json: Map): AppTransaction { + return AppTransaction( + appId = (json["appId"] as Number).toDouble(), + appTransactionId = json["appTransactionId"] as String?, + appVersion = json["appVersion"] as String, + appVersionId = (json["appVersionId"] as Number).toDouble(), + bundleId = json["bundleId"] as String, + deviceVerification = json["deviceVerification"] as String, + deviceVerificationNonce = json["deviceVerificationNonce"] as String, + environment = json["environment"] as String, + originalAppVersion = json["originalAppVersion"] as String, + originalPlatform = json["originalPlatform"] as String?, + originalPurchaseDate = (json["originalPurchaseDate"] as Number).toDouble(), + preorderDate = (json["preorderDate"] as Number?)?.toDouble(), + signedDate = (json["signedDate"] as Number).toDouble(), + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "AppTransaction", + "appId" to appId, + "appTransactionId" to appTransactionId, + "appVersion" to appVersion, + "appVersionId" to appVersionId, + "bundleId" to bundleId, + "deviceVerification" to deviceVerification, + "deviceVerificationNonce" to deviceVerificationNonce, + "environment" to environment, + "originalAppVersion" to originalAppVersion, + "originalPlatform" to originalPlatform, + "originalPurchaseDate" to originalPurchaseDate, + "preorderDate" to preorderDate, + "signedDate" to signedDate, + ) +} public data class DiscountIOS( val identifier: String, @@ -174,8 +387,35 @@ public data class DiscountIOS( val priceAmount: Double, val subscriptionPeriod: String, val type: String -) - +) { + + companion object { + fun fromJson(json: Map): DiscountIOS { + return DiscountIOS( + identifier = json["identifier"] as String, + localizedPrice = json["localizedPrice"] as String?, + numberOfPeriods = (json["numberOfPeriods"] as Number).toInt(), + paymentMode = PaymentModeIOS.fromJson(json["paymentMode"] as String), + price = json["price"] as String, + priceAmount = (json["priceAmount"] as Number).toDouble(), + subscriptionPeriod = json["subscriptionPeriod"] as String, + type = json["type"] as String, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "DiscountIOS", + "identifier" to identifier, + "localizedPrice" to localizedPrice, + "numberOfPeriods" to numberOfPeriods, + "paymentMode" to paymentMode.toJson(), + "price" to price, + "priceAmount" to priceAmount, + "subscriptionPeriod" to subscriptionPeriod, + "type" to type, + ) +} public data class DiscountOfferIOS( /** @@ -198,21 +438,74 @@ public data class DiscountOfferIOS( * Timestamp of discount offer */ val timestamp: Double -) - +) { + + companion object { + fun fromJson(json: Map): DiscountOfferIOS { + return DiscountOfferIOS( + identifier = json["identifier"] as String, + keyIdentifier = json["keyIdentifier"] as String, + nonce = json["nonce"] as String, + signature = json["signature"] as String, + timestamp = (json["timestamp"] as Number).toDouble(), + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "DiscountOfferIOS", + "identifier" to identifier, + "keyIdentifier" to keyIdentifier, + "nonce" to nonce, + "signature" to signature, + "timestamp" to timestamp, + ) +} public data class EntitlementIOS( val jsonRepresentation: String, val sku: String, val transactionId: String -) - +) { + + companion object { + fun fromJson(json: Map): EntitlementIOS { + return EntitlementIOS( + jsonRepresentation = json["jsonRepresentation"] as String, + sku = json["sku"] as String, + transactionId = json["transactionId"] as String, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "EntitlementIOS", + "jsonRepresentation" to jsonRepresentation, + "sku" to sku, + "transactionId" to transactionId, + ) +} public data class FetchProductsResult( val products: List? = null, val subscriptions: List? = null -) - +) { + + companion object { + fun fromJson(json: Map): FetchProductsResult { + return FetchProductsResult( + products = (json["products"] as List<*>?)?.map { Product.fromJson((it as Map)) }, + subscriptions = (json["subscriptions"] as List<*>?)?.map { ProductSubscription.fromJson((it as Map)) }, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "FetchProductsResult", + "products" to products?.map { it.toJson() }, + "subscriptions" to subscriptions?.map { it.toJson() }, + ) +} public data class PricingPhaseAndroid( val billingCycleCount: Int, @@ -221,13 +514,49 @@ public data class PricingPhaseAndroid( val priceAmountMicros: String, val priceCurrencyCode: String, val recurrenceMode: Int -) - +) { + + companion object { + fun fromJson(json: Map): PricingPhaseAndroid { + return PricingPhaseAndroid( + billingCycleCount = (json["billingCycleCount"] as Number).toInt(), + billingPeriod = json["billingPeriod"] as String, + formattedPrice = json["formattedPrice"] as String, + priceAmountMicros = json["priceAmountMicros"] as String, + priceCurrencyCode = json["priceCurrencyCode"] as String, + recurrenceMode = (json["recurrenceMode"] as Number).toInt(), + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "PricingPhaseAndroid", + "billingCycleCount" to billingCycleCount, + "billingPeriod" to billingPeriod, + "formattedPrice" to formattedPrice, + "priceAmountMicros" to priceAmountMicros, + "priceCurrencyCode" to priceCurrencyCode, + "recurrenceMode" to recurrenceMode, + ) +} public data class PricingPhasesAndroid( val pricingPhaseList: List -) - +) { + + companion object { + fun fromJson(json: Map): PricingPhasesAndroid { + return PricingPhasesAndroid( + pricingPhaseList = (json["pricingPhaseList"] as List<*>).map { PricingPhaseAndroid.fromJson((it as Map)) }, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "PricingPhasesAndroid", + "pricingPhaseList" to pricingPhaseList.map { it.toJson() }, + ) +} public data class ProductAndroid( val currency: String, @@ -238,20 +567,74 @@ public data class ProductAndroid( val id: String, val nameAndroid: String, val oneTimePurchaseOfferDetailsAndroid: ProductAndroidOneTimePurchaseOfferDetail? = null, - val platform: Platform, + val platform: IapPlatform, val price: Double? = null, val subscriptionOfferDetailsAndroid: List? = null, val title: String, val type: ProductType -) : ProductCommon, Product - +) : ProductCommon, Product { + + companion object { + fun fromJson(json: Map): ProductAndroid { + return ProductAndroid( + currency = json["currency"] as String, + debugDescription = json["debugDescription"] as String?, + description = json["description"] as String, + displayName = json["displayName"] as String?, + displayPrice = json["displayPrice"] as String, + id = json["id"] as String, + nameAndroid = json["nameAndroid"] as String, + oneTimePurchaseOfferDetailsAndroid = (json["oneTimePurchaseOfferDetailsAndroid"] as Map?)?.let { ProductAndroidOneTimePurchaseOfferDetail.fromJson(it) }, + platform = IapPlatform.fromJson(json["platform"] as String), + price = (json["price"] as Number?)?.toDouble(), + subscriptionOfferDetailsAndroid = (json["subscriptionOfferDetailsAndroid"] as List<*>?)?.map { ProductSubscriptionAndroidOfferDetails.fromJson((it as Map)) }, + title = json["title"] as String, + type = ProductType.fromJson(json["type"] as String), + ) + } + } + + override fun toJson(): Map = mapOf( + "__typename" to "ProductAndroid", + "currency" to currency, + "debugDescription" to debugDescription, + "description" to description, + "displayName" to displayName, + "displayPrice" to displayPrice, + "id" to id, + "nameAndroid" to nameAndroid, + "oneTimePurchaseOfferDetailsAndroid" to oneTimePurchaseOfferDetailsAndroid?.toJson(), + "platform" to platform.toJson(), + "price" to price, + "subscriptionOfferDetailsAndroid" to subscriptionOfferDetailsAndroid?.map { it.toJson() }, + "title" to title, + "type" to type.toJson(), + ) +} public data class ProductAndroidOneTimePurchaseOfferDetail( val formattedPrice: String, val priceAmountMicros: String, val priceCurrencyCode: String -) - +) { + + companion object { + fun fromJson(json: Map): ProductAndroidOneTimePurchaseOfferDetail { + return ProductAndroidOneTimePurchaseOfferDetail( + formattedPrice = json["formattedPrice"] as String, + priceAmountMicros = json["priceAmountMicros"] as String, + priceCurrencyCode = json["priceCurrencyCode"] as String, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "ProductAndroidOneTimePurchaseOfferDetail", + "formattedPrice" to formattedPrice, + "priceAmountMicros" to priceAmountMicros, + "priceCurrencyCode" to priceCurrencyCode, + ) +} public data class ProductIOS( val currency: String, @@ -263,14 +646,55 @@ public data class ProductIOS( val id: String, val isFamilyShareableIOS: Boolean, val jsonRepresentationIOS: String, - val platform: Platform, + val platform: IapPlatform, val price: Double? = null, val subscriptionInfoIOS: SubscriptionInfoIOS? = null, val title: String, val type: ProductType, val typeIOS: ProductTypeIOS -) : ProductCommon, Product - +) : ProductCommon, Product { + + companion object { + fun fromJson(json: Map): ProductIOS { + return ProductIOS( + currency = json["currency"] as String, + debugDescription = json["debugDescription"] as String?, + description = json["description"] as String, + displayName = json["displayName"] as String?, + displayNameIOS = json["displayNameIOS"] as String, + displayPrice = json["displayPrice"] as String, + id = json["id"] as String, + isFamilyShareableIOS = json["isFamilyShareableIOS"] as Boolean, + jsonRepresentationIOS = json["jsonRepresentationIOS"] as String, + platform = IapPlatform.fromJson(json["platform"] as String), + price = (json["price"] as Number?)?.toDouble(), + subscriptionInfoIOS = (json["subscriptionInfoIOS"] as Map?)?.let { SubscriptionInfoIOS.fromJson(it) }, + title = json["title"] as String, + type = ProductType.fromJson(json["type"] as String), + typeIOS = ProductTypeIOS.fromJson(json["typeIOS"] as String), + ) + } + } + + override fun toJson(): Map = mapOf( + "__typename" to "ProductIOS", + "currency" to currency, + "debugDescription" to debugDescription, + "description" to description, + "displayName" to displayName, + "displayNameIOS" to displayNameIOS, + "displayPrice" to displayPrice, + "id" to id, + "isFamilyShareableIOS" to isFamilyShareableIOS, + "jsonRepresentationIOS" to jsonRepresentationIOS, + "platform" to platform.toJson(), + "price" to price, + "subscriptionInfoIOS" to subscriptionInfoIOS?.toJson(), + "title" to title, + "type" to type.toJson(), + "typeIOS" to typeIOS.toJson(), + ) +} public data class ProductSubscriptionAndroid( val currency: String, @@ -281,13 +705,50 @@ public data class ProductSubscriptionAndroid( val id: String, val nameAndroid: String, val oneTimePurchaseOfferDetailsAndroid: ProductAndroidOneTimePurchaseOfferDetail? = null, - val platform: Platform, + val platform: IapPlatform, val price: Double? = null, val subscriptionOfferDetailsAndroid: List, val title: String, val type: ProductType -) : ProductCommon, ProductSubscription - +) : ProductCommon, ProductSubscription { + + companion object { + fun fromJson(json: Map): ProductSubscriptionAndroid { + return ProductSubscriptionAndroid( + currency = json["currency"] as String, + debugDescription = json["debugDescription"] as String?, + description = json["description"] as String, + displayName = json["displayName"] as String?, + displayPrice = json["displayPrice"] as String, + id = json["id"] as String, + nameAndroid = json["nameAndroid"] as String, + oneTimePurchaseOfferDetailsAndroid = (json["oneTimePurchaseOfferDetailsAndroid"] as Map?)?.let { ProductAndroidOneTimePurchaseOfferDetail.fromJson(it) }, + platform = IapPlatform.fromJson(json["platform"] as String), + price = (json["price"] as Number?)?.toDouble(), + subscriptionOfferDetailsAndroid = (json["subscriptionOfferDetailsAndroid"] as List<*>).map { ProductSubscriptionAndroidOfferDetails.fromJson((it as Map)) }, + title = json["title"] as String, + type = ProductType.fromJson(json["type"] as String), + ) + } + } + + override fun toJson(): Map = mapOf( + "__typename" to "ProductSubscriptionAndroid", + "currency" to currency, + "debugDescription" to debugDescription, + "description" to description, + "displayName" to displayName, + "displayPrice" to displayPrice, + "id" to id, + "nameAndroid" to nameAndroid, + "oneTimePurchaseOfferDetailsAndroid" to oneTimePurchaseOfferDetailsAndroid?.toJson(), + "platform" to platform.toJson(), + "price" to price, + "subscriptionOfferDetailsAndroid" to subscriptionOfferDetailsAndroid.map { it.toJson() }, + "title" to title, + "type" to type.toJson(), + ) +} public data class ProductSubscriptionAndroidOfferDetails( val basePlanId: String, @@ -295,8 +756,29 @@ public data class ProductSubscriptionAndroidOfferDetails( val offerTags: List, val offerToken: String, val pricingPhases: PricingPhasesAndroid -) - +) { + + companion object { + fun fromJson(json: Map): ProductSubscriptionAndroidOfferDetails { + return ProductSubscriptionAndroidOfferDetails( + basePlanId = json["basePlanId"] as String, + offerId = json["offerId"] as String?, + offerTags = (json["offerTags"] as List<*>).map { it as String }, + offerToken = json["offerToken"] as String, + pricingPhases = PricingPhasesAndroid.fromJson((json["pricingPhases"] as Map)), + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "ProductSubscriptionAndroidOfferDetails", + "basePlanId" to basePlanId, + "offerId" to offerId, + "offerTags" to offerTags.map { it }, + "offerToken" to offerToken, + "pricingPhases" to pricingPhases.toJson(), + ) +} public data class ProductSubscriptionIOS( val currency: String, @@ -314,7 +796,7 @@ public data class ProductSubscriptionIOS( val introductoryPriceSubscriptionPeriodIOS: SubscriptionPeriodIOS? = null, val isFamilyShareableIOS: Boolean, val jsonRepresentationIOS: String, - val platform: Platform, + val platform: IapPlatform, val price: Double? = null, val subscriptionInfoIOS: SubscriptionInfoIOS? = null, val subscriptionPeriodNumberIOS: String? = null, @@ -322,8 +804,65 @@ public data class ProductSubscriptionIOS( val title: String, val type: ProductType, val typeIOS: ProductTypeIOS -) : ProductCommon, ProductSubscription - +) : ProductCommon, ProductSubscription { + + companion object { + fun fromJson(json: Map): ProductSubscriptionIOS { + return ProductSubscriptionIOS( + currency = json["currency"] as String, + debugDescription = json["debugDescription"] as String?, + description = json["description"] as String, + discountsIOS = (json["discountsIOS"] as List<*>?)?.map { DiscountIOS.fromJson((it as Map)) }, + displayName = json["displayName"] as String?, + displayNameIOS = json["displayNameIOS"] as String, + displayPrice = json["displayPrice"] as String, + id = json["id"] as String, + introductoryPriceAsAmountIOS = json["introductoryPriceAsAmountIOS"] as String?, + introductoryPriceIOS = json["introductoryPriceIOS"] as String?, + introductoryPriceNumberOfPeriodsIOS = json["introductoryPriceNumberOfPeriodsIOS"] as String?, + introductoryPricePaymentModeIOS = (json["introductoryPricePaymentModeIOS"] as String?)?.let { PaymentModeIOS.fromJson(it) }, + introductoryPriceSubscriptionPeriodIOS = (json["introductoryPriceSubscriptionPeriodIOS"] as String?)?.let { SubscriptionPeriodIOS.fromJson(it) }, + isFamilyShareableIOS = json["isFamilyShareableIOS"] as Boolean, + jsonRepresentationIOS = json["jsonRepresentationIOS"] as String, + platform = IapPlatform.fromJson(json["platform"] as String), + price = (json["price"] as Number?)?.toDouble(), + subscriptionInfoIOS = (json["subscriptionInfoIOS"] as Map?)?.let { SubscriptionInfoIOS.fromJson(it) }, + subscriptionPeriodNumberIOS = json["subscriptionPeriodNumberIOS"] as String?, + subscriptionPeriodUnitIOS = (json["subscriptionPeriodUnitIOS"] as String?)?.let { SubscriptionPeriodIOS.fromJson(it) }, + title = json["title"] as String, + type = ProductType.fromJson(json["type"] as String), + typeIOS = ProductTypeIOS.fromJson(json["typeIOS"] as String), + ) + } + } + + override fun toJson(): Map = mapOf( + "__typename" to "ProductSubscriptionIOS", + "currency" to currency, + "debugDescription" to debugDescription, + "description" to description, + "discountsIOS" to discountsIOS?.map { it.toJson() }, + "displayName" to displayName, + "displayNameIOS" to displayNameIOS, + "displayPrice" to displayPrice, + "id" to id, + "introductoryPriceAsAmountIOS" to introductoryPriceAsAmountIOS, + "introductoryPriceIOS" to introductoryPriceIOS, + "introductoryPriceNumberOfPeriodsIOS" to introductoryPriceNumberOfPeriodsIOS, + "introductoryPricePaymentModeIOS" to introductoryPricePaymentModeIOS?.toJson(), + "introductoryPriceSubscriptionPeriodIOS" to introductoryPriceSubscriptionPeriodIOS?.toJson(), + "isFamilyShareableIOS" to isFamilyShareableIOS, + "jsonRepresentationIOS" to jsonRepresentationIOS, + "platform" to platform.toJson(), + "price" to price, + "subscriptionInfoIOS" to subscriptionInfoIOS?.toJson(), + "subscriptionPeriodNumberIOS" to subscriptionPeriodNumberIOS, + "subscriptionPeriodUnitIOS" to subscriptionPeriodUnitIOS?.toJson(), + "title" to title, + "type" to type.toJson(), + "typeIOS" to typeIOS.toJson(), + ) +} public data class PurchaseAndroid( val autoRenewingAndroid: Boolean? = null, @@ -336,22 +875,84 @@ public data class PurchaseAndroid( val obfuscatedAccountIdAndroid: String? = null, val obfuscatedProfileIdAndroid: String? = null, val packageNameAndroid: String? = null, - val platform: Platform, + val platform: IapPlatform, val productId: String, val purchaseState: PurchaseState, val purchaseToken: String? = null, val quantity: Int, val signatureAndroid: String? = null, val transactionDate: Double -) : PurchaseCommon, Purchase - +) : PurchaseCommon, Purchase { + + companion object { + fun fromJson(json: Map): PurchaseAndroid { + return PurchaseAndroid( + autoRenewingAndroid = json["autoRenewingAndroid"] as Boolean?, + dataAndroid = json["dataAndroid"] as String?, + developerPayloadAndroid = json["developerPayloadAndroid"] as String?, + id = json["id"] as String, + ids = (json["ids"] as List<*>?)?.map { it as String }, + isAcknowledgedAndroid = json["isAcknowledgedAndroid"] as Boolean?, + isAutoRenewing = json["isAutoRenewing"] as Boolean, + obfuscatedAccountIdAndroid = json["obfuscatedAccountIdAndroid"] as String?, + obfuscatedProfileIdAndroid = json["obfuscatedProfileIdAndroid"] as String?, + packageNameAndroid = json["packageNameAndroid"] as String?, + platform = IapPlatform.fromJson(json["platform"] as String), + productId = json["productId"] as String, + purchaseState = PurchaseState.fromJson(json["purchaseState"] as String), + purchaseToken = json["purchaseToken"] as String?, + quantity = (json["quantity"] as Number).toInt(), + signatureAndroid = json["signatureAndroid"] as String?, + transactionDate = (json["transactionDate"] as Number).toDouble(), + ) + } + } + + override fun toJson(): Map = mapOf( + "__typename" to "PurchaseAndroid", + "autoRenewingAndroid" to autoRenewingAndroid, + "dataAndroid" to dataAndroid, + "developerPayloadAndroid" to developerPayloadAndroid, + "id" to id, + "ids" to ids?.map { it }, + "isAcknowledgedAndroid" to isAcknowledgedAndroid, + "isAutoRenewing" to isAutoRenewing, + "obfuscatedAccountIdAndroid" to obfuscatedAccountIdAndroid, + "obfuscatedProfileIdAndroid" to obfuscatedProfileIdAndroid, + "packageNameAndroid" to packageNameAndroid, + "platform" to platform.toJson(), + "productId" to productId, + "purchaseState" to purchaseState.toJson(), + "purchaseToken" to purchaseToken, + "quantity" to quantity, + "signatureAndroid" to signatureAndroid, + "transactionDate" to transactionDate, + ) +} public data class PurchaseError( val code: ErrorCode, val message: String, val productId: String? = null -) - +) { + + companion object { + fun fromJson(json: Map): PurchaseError { + return PurchaseError( + code = ErrorCode.fromJson(json["code"] as String), + message = json["message"] as String, + productId = json["productId"] as String?, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "PurchaseError", + "code" to code.toJson(), + "message" to message, + "productId" to productId, + ) +} public data class PurchaseIOS( val appAccountToken: String? = null, @@ -369,7 +970,7 @@ public data class PurchaseIOS( val originalTransactionDateIOS: Double? = null, val originalTransactionIdentifierIOS: String? = null, val ownershipTypeIOS: String? = null, - val platform: Platform, + val platform: IapPlatform, val productId: String, val purchaseState: PurchaseState, val purchaseToken: String? = null, @@ -384,15 +985,103 @@ public data class PurchaseIOS( val transactionDate: Double, val transactionReasonIOS: String? = null, val webOrderLineItemIdIOS: String? = null -) : PurchaseCommon, Purchase - +) : PurchaseCommon, Purchase { + + companion object { + fun fromJson(json: Map): PurchaseIOS { + return PurchaseIOS( + appAccountToken = json["appAccountToken"] as String?, + appBundleIdIOS = json["appBundleIdIOS"] as String?, + countryCodeIOS = json["countryCodeIOS"] as String?, + currencyCodeIOS = json["currencyCodeIOS"] as String?, + currencySymbolIOS = json["currencySymbolIOS"] as String?, + environmentIOS = json["environmentIOS"] as String?, + expirationDateIOS = (json["expirationDateIOS"] as Number?)?.toDouble(), + id = json["id"] as String, + ids = (json["ids"] as List<*>?)?.map { it as String }, + isAutoRenewing = json["isAutoRenewing"] as Boolean, + isUpgradedIOS = json["isUpgradedIOS"] as Boolean?, + offerIOS = (json["offerIOS"] as Map?)?.let { PurchaseOfferIOS.fromJson(it) }, + originalTransactionDateIOS = (json["originalTransactionDateIOS"] as Number?)?.toDouble(), + originalTransactionIdentifierIOS = json["originalTransactionIdentifierIOS"] as String?, + ownershipTypeIOS = json["ownershipTypeIOS"] as String?, + platform = IapPlatform.fromJson(json["platform"] as String), + productId = json["productId"] as String, + purchaseState = PurchaseState.fromJson(json["purchaseState"] as String), + purchaseToken = json["purchaseToken"] as String?, + quantity = (json["quantity"] as Number).toInt(), + quantityIOS = (json["quantityIOS"] as Number?)?.toInt(), + reasonIOS = json["reasonIOS"] as String?, + reasonStringRepresentationIOS = json["reasonStringRepresentationIOS"] as String?, + revocationDateIOS = (json["revocationDateIOS"] as Number?)?.toDouble(), + revocationReasonIOS = json["revocationReasonIOS"] as String?, + storefrontCountryCodeIOS = json["storefrontCountryCodeIOS"] as String?, + subscriptionGroupIdIOS = json["subscriptionGroupIdIOS"] as String?, + transactionDate = (json["transactionDate"] as Number).toDouble(), + transactionReasonIOS = json["transactionReasonIOS"] as String?, + webOrderLineItemIdIOS = json["webOrderLineItemIdIOS"] as String?, + ) + } + } + + override fun toJson(): Map = mapOf( + "__typename" to "PurchaseIOS", + "appAccountToken" to appAccountToken, + "appBundleIdIOS" to appBundleIdIOS, + "countryCodeIOS" to countryCodeIOS, + "currencyCodeIOS" to currencyCodeIOS, + "currencySymbolIOS" to currencySymbolIOS, + "environmentIOS" to environmentIOS, + "expirationDateIOS" to expirationDateIOS, + "id" to id, + "ids" to ids?.map { it }, + "isAutoRenewing" to isAutoRenewing, + "isUpgradedIOS" to isUpgradedIOS, + "offerIOS" to offerIOS?.toJson(), + "originalTransactionDateIOS" to originalTransactionDateIOS, + "originalTransactionIdentifierIOS" to originalTransactionIdentifierIOS, + "ownershipTypeIOS" to ownershipTypeIOS, + "platform" to platform.toJson(), + "productId" to productId, + "purchaseState" to purchaseState.toJson(), + "purchaseToken" to purchaseToken, + "quantity" to quantity, + "quantityIOS" to quantityIOS, + "reasonIOS" to reasonIOS, + "reasonStringRepresentationIOS" to reasonStringRepresentationIOS, + "revocationDateIOS" to revocationDateIOS, + "revocationReasonIOS" to revocationReasonIOS, + "storefrontCountryCodeIOS" to storefrontCountryCodeIOS, + "subscriptionGroupIdIOS" to subscriptionGroupIdIOS, + "transactionDate" to transactionDate, + "transactionReasonIOS" to transactionReasonIOS, + "webOrderLineItemIdIOS" to webOrderLineItemIdIOS, + ) +} public data class PurchaseOfferIOS( val id: String, val paymentMode: String, val type: String -) - +) { + + companion object { + fun fromJson(json: Map): PurchaseOfferIOS { + return PurchaseOfferIOS( + id = json["id"] as String, + paymentMode = json["paymentMode"] as String, + type = json["type"] as String, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "PurchaseOfferIOS", + "id" to id, + "paymentMode" to paymentMode, + "type" to type, + ) +} public data class ReceiptValidationResultAndroid( val autoRenewing: Boolean, @@ -400,7 +1089,7 @@ public data class ReceiptValidationResultAndroid( val cancelDate: Double? = null, val cancelReason: String? = null, val deferredDate: Double? = null, - val deferredSku: Double? = null, + val deferredSku: String? = null, val freeTrialEndDate: Double, val gracePeriodEndDate: Double, val parentProductId: String, @@ -413,8 +1102,55 @@ public data class ReceiptValidationResultAndroid( val term: String, val termSku: String, val testTransaction: Boolean -) : ReceiptValidationResult - +) : ReceiptValidationResult { + + companion object { + fun fromJson(json: Map): ReceiptValidationResultAndroid { + return ReceiptValidationResultAndroid( + autoRenewing = json["autoRenewing"] as Boolean, + betaProduct = json["betaProduct"] as Boolean, + cancelDate = (json["cancelDate"] as Number?)?.toDouble(), + cancelReason = json["cancelReason"] as String?, + deferredDate = (json["deferredDate"] as Number?)?.toDouble(), + deferredSku = json["deferredSku"] as String?, + freeTrialEndDate = (json["freeTrialEndDate"] as Number).toDouble(), + gracePeriodEndDate = (json["gracePeriodEndDate"] as Number).toDouble(), + parentProductId = json["parentProductId"] as String, + productId = json["productId"] as String, + productType = json["productType"] as String, + purchaseDate = (json["purchaseDate"] as Number).toDouble(), + quantity = (json["quantity"] as Number).toInt(), + receiptId = json["receiptId"] as String, + renewalDate = (json["renewalDate"] as Number).toDouble(), + term = json["term"] as String, + termSku = json["termSku"] as String, + testTransaction = json["testTransaction"] as Boolean, + ) + } + } + + override fun toJson(): Map = mapOf( + "__typename" to "ReceiptValidationResultAndroid", + "autoRenewing" to autoRenewing, + "betaProduct" to betaProduct, + "cancelDate" to cancelDate, + "cancelReason" to cancelReason, + "deferredDate" to deferredDate, + "deferredSku" to deferredSku, + "freeTrialEndDate" to freeTrialEndDate, + "gracePeriodEndDate" to gracePeriodEndDate, + "parentProductId" to parentProductId, + "productId" to productId, + "productType" to productType, + "purchaseDate" to purchaseDate, + "quantity" to quantity, + "receiptId" to receiptId, + "renewalDate" to renewalDate, + "term" to term, + "termSku" to termSku, + "testTransaction" to testTransaction, + ) +} public data class ReceiptValidationResultIOS( /** @@ -433,35 +1169,120 @@ public data class ReceiptValidationResultIOS( * Receipt data string */ val receiptData: String -) : ReceiptValidationResult - +) : ReceiptValidationResult { + + companion object { + fun fromJson(json: Map): ReceiptValidationResultIOS { + return ReceiptValidationResultIOS( + isValid = json["isValid"] as Boolean, + jwsRepresentation = json["jwsRepresentation"] as String, + latestTransaction = (json["latestTransaction"] as Map?)?.let { Purchase.fromJson(it) }, + receiptData = json["receiptData"] as String, + ) + } + } + + override fun toJson(): Map = mapOf( + "__typename" to "ReceiptValidationResultIOS", + "isValid" to isValid, + "jwsRepresentation" to jwsRepresentation, + "latestTransaction" to latestTransaction?.toJson(), + "receiptData" to receiptData, + ) +} public data class RefundResultIOS( val message: String? = null, val status: String -) - +) { + + companion object { + fun fromJson(json: Map): RefundResultIOS { + return RefundResultIOS( + message = json["message"] as String?, + status = json["status"] as String, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "RefundResultIOS", + "message" to message, + "status" to status, + ) +} public data class RenewalInfoIOS( val autoRenewPreference: String? = null, val jsonRepresentation: String? = null, val willAutoRenew: Boolean -) - +) { + + companion object { + fun fromJson(json: Map): RenewalInfoIOS { + return RenewalInfoIOS( + autoRenewPreference = json["autoRenewPreference"] as String?, + jsonRepresentation = json["jsonRepresentation"] as String?, + willAutoRenew = json["willAutoRenew"] as Boolean, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "RenewalInfoIOS", + "autoRenewPreference" to autoRenewPreference, + "jsonRepresentation" to jsonRepresentation, + "willAutoRenew" to willAutoRenew, + ) +} public data class RequestPurchaseResult( val purchase: Purchase? = null, val purchases: List? = null -) - +) { + + companion object { + fun fromJson(json: Map): RequestPurchaseResult { + return RequestPurchaseResult( + purchase = (json["purchase"] as Map?)?.let { Purchase.fromJson(it) }, + purchases = (json["purchases"] as List<*>?)?.map { Purchase.fromJson((it as Map)) }, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "RequestPurchaseResult", + "purchase" to purchase?.toJson(), + "purchases" to purchases?.map { it.toJson() }, + ) +} public data class SubscriptionInfoIOS( val introductoryOffer: SubscriptionOfferIOS? = null, val promotionalOffers: List? = null, val subscriptionGroupId: String, val subscriptionPeriod: SubscriptionPeriodValueIOS -) - +) { + + companion object { + fun fromJson(json: Map): SubscriptionInfoIOS { + return SubscriptionInfoIOS( + introductoryOffer = (json["introductoryOffer"] as Map?)?.let { SubscriptionOfferIOS.fromJson(it) }, + promotionalOffers = (json["promotionalOffers"] as List<*>?)?.map { SubscriptionOfferIOS.fromJson((it as Map)) }, + subscriptionGroupId = json["subscriptionGroupId"] as String, + subscriptionPeriod = SubscriptionPeriodValueIOS.fromJson((json["subscriptionPeriod"] as Map)), + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "SubscriptionInfoIOS", + "introductoryOffer" to introductoryOffer?.toJson(), + "promotionalOffers" to promotionalOffers?.map { it.toJson() }, + "subscriptionGroupId" to subscriptionGroupId, + "subscriptionPeriod" to subscriptionPeriod.toJson(), + ) +} public data class SubscriptionOfferIOS( val displayPrice: String, @@ -471,25 +1292,93 @@ public data class SubscriptionOfferIOS( val periodCount: Int, val price: Double, val type: SubscriptionOfferTypeIOS -) - +) { + + companion object { + fun fromJson(json: Map): SubscriptionOfferIOS { + return SubscriptionOfferIOS( + displayPrice = json["displayPrice"] as String, + id = json["id"] as String, + paymentMode = PaymentModeIOS.fromJson(json["paymentMode"] as String), + period = SubscriptionPeriodValueIOS.fromJson((json["period"] as Map)), + periodCount = (json["periodCount"] as Number).toInt(), + price = (json["price"] as Number).toDouble(), + type = SubscriptionOfferTypeIOS.fromJson(json["type"] as String), + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "SubscriptionOfferIOS", + "displayPrice" to displayPrice, + "id" to id, + "paymentMode" to paymentMode.toJson(), + "period" to period.toJson(), + "periodCount" to periodCount, + "price" to price, + "type" to type.toJson(), + ) +} public data class SubscriptionPeriodValueIOS( val unit: SubscriptionPeriodIOS, val value: Int -) - +) { + + companion object { + fun fromJson(json: Map): SubscriptionPeriodValueIOS { + return SubscriptionPeriodValueIOS( + unit = SubscriptionPeriodIOS.fromJson(json["unit"] as String), + value = (json["value"] as Number).toInt(), + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "SubscriptionPeriodValueIOS", + "unit" to unit.toJson(), + "value" to value, + ) +} public data class SubscriptionStatusIOS( val renewalInfo: RenewalInfoIOS? = null, val state: String -) - +) { + + companion object { + fun fromJson(json: Map): SubscriptionStatusIOS { + return SubscriptionStatusIOS( + renewalInfo = (json["renewalInfo"] as Map?)?.let { RenewalInfoIOS.fromJson(it) }, + state = json["state"] as String, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "SubscriptionStatusIOS", + "renewalInfo" to renewalInfo?.toJson(), + "state" to state, + ) +} public data class VoidResult( val success: Boolean -) - +) { + + companion object { + fun fromJson(json: Map): VoidResult { + return VoidResult( + success = json["success"] as Boolean, + ) + } + } + + fun toJson(): Map = mapOf( + "__typename" to "VoidResult", + "success" to success, + ) +} // MARK: - Input Objects @@ -502,7 +1391,21 @@ public data class AndroidSubscriptionOfferInput( * Product SKU */ val sku: String -) +) { + companion object { + fun fromJson(json: Map): AndroidSubscriptionOfferInput { + return AndroidSubscriptionOfferInput( + offerToken = json["offerToken"] as String, + sku = json["sku"] as String, + ) + } + } + + fun toJson(): Map = mapOf( + "offerToken" to offerToken, + "sku" to sku, + ) +} public data class DeepLinkOptions( /** @@ -513,7 +1416,21 @@ public data class DeepLinkOptions( * Android SKU to open (required on Android) */ val skuAndroid: String? = null -) +) { + companion object { + fun fromJson(json: Map): DeepLinkOptions { + return DeepLinkOptions( + packageNameAndroid = json["packageNameAndroid"] as String?, + skuAndroid = json["skuAndroid"] as String?, + ) + } + } + + fun toJson(): Map = mapOf( + "packageNameAndroid" to packageNameAndroid, + "skuAndroid" to skuAndroid, + ) +} public data class DiscountOfferInputIOS( /** @@ -536,24 +1453,86 @@ public data class DiscountOfferInputIOS( * Timestamp of discount offer */ val timestamp: Double -) +) { + companion object { + fun fromJson(json: Map): DiscountOfferInputIOS { + return DiscountOfferInputIOS( + identifier = json["identifier"] as String, + keyIdentifier = json["keyIdentifier"] as String, + nonce = json["nonce"] as String, + signature = json["signature"] as String, + timestamp = (json["timestamp"] as Number).toDouble(), + ) + } + } + + fun toJson(): Map = mapOf( + "identifier" to identifier, + "keyIdentifier" to keyIdentifier, + "nonce" to nonce, + "signature" to signature, + "timestamp" to timestamp, + ) +} public data class ProductRequest( val skus: List, val type: ProductQueryType? = null -) +) { + companion object { + fun fromJson(json: Map): ProductRequest { + return ProductRequest( + skus = (json["skus"] as List<*>).map { it as String }, + type = (json["type"] as String?)?.let { ProductQueryType.fromJson(it) }, + ) + } + } + + fun toJson(): Map = mapOf( + "skus" to skus.map { it }, + "type" to type?.toJson(), + ) +} public data class PurchaseInput( val id: String, val ids: List? = null, val isAutoRenewing: Boolean, - val platform: Platform, + val platform: IapPlatform, val productId: String, val purchaseState: PurchaseState, val purchaseToken: String? = null, val quantity: Int, val transactionDate: Double -) +) { + companion object { + fun fromJson(json: Map): PurchaseInput { + return PurchaseInput( + id = json["id"] as String, + ids = (json["ids"] as List<*>?)?.map { it as String }, + isAutoRenewing = json["isAutoRenewing"] as Boolean, + platform = IapPlatform.fromJson(json["platform"] as String), + productId = json["productId"] as String, + purchaseState = PurchaseState.fromJson(json["purchaseState"] as String), + purchaseToken = json["purchaseToken"] as String?, + quantity = (json["quantity"] as Number).toInt(), + transactionDate = (json["transactionDate"] as Number).toDouble(), + ) + } + } + + fun toJson(): Map = mapOf( + "id" to id, + "ids" to ids?.map { it }, + "isAutoRenewing" to isAutoRenewing, + "platform" to platform.toJson(), + "productId" to productId, + "purchaseState" to purchaseState.toJson(), + "purchaseToken" to purchaseToken, + "quantity" to quantity, + "transactionDate" to transactionDate, + ) +} public data class PurchaseOptions( /** @@ -564,7 +1543,21 @@ public data class PurchaseOptions( * Limit to currently active items on iOS */ val onlyIncludeActiveItemsIOS: Boolean? = null -) +) { + companion object { + fun fromJson(json: Map): PurchaseOptions { + return PurchaseOptions( + alsoPublishToEventListenerIOS = json["alsoPublishToEventListenerIOS"] as Boolean?, + onlyIncludeActiveItemsIOS = json["onlyIncludeActiveItemsIOS"] as Boolean?, + ) + } + } + + fun toJson(): Map = mapOf( + "alsoPublishToEventListenerIOS" to alsoPublishToEventListenerIOS, + "onlyIncludeActiveItemsIOS" to onlyIncludeActiveItemsIOS, + ) +} public data class PurchaseParams( /** @@ -579,14 +1572,48 @@ public data class PurchaseParams( * Explicit purchase type hint (defaults to in-app) */ val type: ProductQueryType? = null -) +) { + companion object { + fun fromJson(json: Map): PurchaseParams { + return PurchaseParams( + requestPurchase = (json["requestPurchase"] as Map?)?.let { RequestPurchasePropsByPlatforms.fromJson(it) }, + requestSubscription = (json["requestSubscription"] as Map?)?.let { RequestSubscriptionPropsByPlatforms.fromJson(it) }, + type = (json["type"] as String?)?.let { ProductQueryType.fromJson(it) }, + ) + } + } + + fun toJson(): Map = mapOf( + "requestPurchase" to requestPurchase?.toJson(), + "requestSubscription" to requestSubscription?.toJson(), + "type" to type?.toJson(), + ) +} public data class ReceiptValidationAndroidOptions( val accessToken: String, val isSub: Boolean? = null, val packageName: String, val productToken: String -) +) { + companion object { + fun fromJson(json: Map): ReceiptValidationAndroidOptions { + return ReceiptValidationAndroidOptions( + accessToken = json["accessToken"] as String, + isSub = json["isSub"] as Boolean?, + packageName = json["packageName"] as String, + productToken = json["productToken"] as String, + ) + } + } + + fun toJson(): Map = mapOf( + "accessToken" to accessToken, + "isSub" to isSub, + "packageName" to packageName, + "productToken" to productToken, + ) +} public data class ReceiptValidationProps( /** @@ -597,7 +1624,21 @@ public data class ReceiptValidationProps( * Product SKU to validate */ val sku: String -) +) { + companion object { + fun fromJson(json: Map): ReceiptValidationProps { + return ReceiptValidationProps( + androidOptions = (json["androidOptions"] as Map?)?.let { ReceiptValidationAndroidOptions.fromJson(it) }, + sku = json["sku"] as String, + ) + } + } + + fun toJson(): Map = mapOf( + "androidOptions" to androidOptions?.toJson(), + "sku" to sku, + ) +} public data class RequestPurchaseAndroidProps( /** @@ -616,7 +1657,25 @@ public data class RequestPurchaseAndroidProps( * List of product SKUs */ val skus: List -) +) { + companion object { + fun fromJson(json: Map): RequestPurchaseAndroidProps { + return RequestPurchaseAndroidProps( + isOfferPersonalized = json["isOfferPersonalized"] as Boolean?, + obfuscatedAccountIdAndroid = json["obfuscatedAccountIdAndroid"] as String?, + obfuscatedProfileIdAndroid = json["obfuscatedProfileIdAndroid"] as String?, + skus = (json["skus"] as List<*>).map { it as String }, + ) + } + } + + fun toJson(): Map = mapOf( + "isOfferPersonalized" to isOfferPersonalized, + "obfuscatedAccountIdAndroid" to obfuscatedAccountIdAndroid, + "obfuscatedProfileIdAndroid" to obfuscatedProfileIdAndroid, + "skus" to skus.map { it }, + ) +} public data class RequestPurchaseIosProps( /** @@ -639,7 +1698,27 @@ public data class RequestPurchaseIosProps( * Discount offer to apply */ val withOffer: DiscountOfferInputIOS? = null -) +) { + companion object { + fun fromJson(json: Map): RequestPurchaseIosProps { + return RequestPurchaseIosProps( + andDangerouslyFinishTransactionAutomatically = json["andDangerouslyFinishTransactionAutomatically"] as Boolean?, + appAccountToken = json["appAccountToken"] as String?, + quantity = (json["quantity"] as Number?)?.toInt(), + sku = json["sku"] as String, + withOffer = (json["withOffer"] as Map?)?.let { DiscountOfferInputIOS.fromJson(it) }, + ) + } + } + + fun toJson(): Map = mapOf( + "andDangerouslyFinishTransactionAutomatically" to andDangerouslyFinishTransactionAutomatically, + "appAccountToken" to appAccountToken, + "quantity" to quantity, + "sku" to sku, + "withOffer" to withOffer?.toJson(), + ) +} public data class RequestPurchaseProps( /** @@ -650,7 +1729,21 @@ public data class RequestPurchaseProps( * iOS-specific purchase parameters */ val ios: RequestPurchaseIosProps? = null -) +) { + companion object { + fun fromJson(json: Map): RequestPurchaseProps { + return RequestPurchaseProps( + android = (json["android"] as Map?)?.let { RequestPurchaseAndroidProps.fromJson(it) }, + ios = (json["ios"] as Map?)?.let { RequestPurchaseIosProps.fromJson(it) }, + ) + } + } + + fun toJson(): Map = mapOf( + "android" to android?.toJson(), + "ios" to ios?.toJson(), + ) +} public data class RequestPurchasePropsByPlatforms( /** @@ -661,7 +1754,21 @@ public data class RequestPurchasePropsByPlatforms( * iOS-specific purchase parameters */ val ios: RequestPurchaseIosProps? = null -) +) { + companion object { + fun fromJson(json: Map): RequestPurchasePropsByPlatforms { + return RequestPurchasePropsByPlatforms( + android = (json["android"] as Map?)?.let { RequestPurchaseAndroidProps.fromJson(it) }, + ios = (json["ios"] as Map?)?.let { RequestPurchaseIosProps.fromJson(it) }, + ) + } + } + + fun toJson(): Map = mapOf( + "android" to android?.toJson(), + "ios" to ios?.toJson(), + ) +} public data class RequestSubscriptionAndroidProps( /** @@ -692,7 +1799,31 @@ public data class RequestSubscriptionAndroidProps( * Subscription offers */ val subscriptionOffers: List? = null -) +) { + companion object { + fun fromJson(json: Map): RequestSubscriptionAndroidProps { + return RequestSubscriptionAndroidProps( + isOfferPersonalized = json["isOfferPersonalized"] as Boolean?, + obfuscatedAccountIdAndroid = json["obfuscatedAccountIdAndroid"] as String?, + obfuscatedProfileIdAndroid = json["obfuscatedProfileIdAndroid"] as String?, + purchaseTokenAndroid = json["purchaseTokenAndroid"] as String?, + replacementModeAndroid = (json["replacementModeAndroid"] as Number?)?.toInt(), + skus = (json["skus"] as List<*>).map { it as String }, + subscriptionOffers = (json["subscriptionOffers"] as List<*>?)?.map { AndroidSubscriptionOfferInput.fromJson((it as Map)) }, + ) + } + } + + fun toJson(): Map = mapOf( + "isOfferPersonalized" to isOfferPersonalized, + "obfuscatedAccountIdAndroid" to obfuscatedAccountIdAndroid, + "obfuscatedProfileIdAndroid" to obfuscatedProfileIdAndroid, + "purchaseTokenAndroid" to purchaseTokenAndroid, + "replacementModeAndroid" to replacementModeAndroid, + "skus" to skus.map { it }, + "subscriptionOffers" to subscriptionOffers?.map { it.toJson() }, + ) +} public data class RequestSubscriptionIosProps( val andDangerouslyFinishTransactionAutomatically: Boolean? = null, @@ -700,7 +1831,27 @@ public data class RequestSubscriptionIosProps( val quantity: Int? = null, val sku: String, val withOffer: DiscountOfferInputIOS? = null -) +) { + companion object { + fun fromJson(json: Map): RequestSubscriptionIosProps { + return RequestSubscriptionIosProps( + andDangerouslyFinishTransactionAutomatically = json["andDangerouslyFinishTransactionAutomatically"] as Boolean?, + appAccountToken = json["appAccountToken"] as String?, + quantity = (json["quantity"] as Number?)?.toInt(), + sku = json["sku"] as String, + withOffer = (json["withOffer"] as Map?)?.let { DiscountOfferInputIOS.fromJson(it) }, + ) + } + } + + fun toJson(): Map = mapOf( + "andDangerouslyFinishTransactionAutomatically" to andDangerouslyFinishTransactionAutomatically, + "appAccountToken" to appAccountToken, + "quantity" to quantity, + "sku" to sku, + "withOffer" to withOffer?.toJson(), + ) +} public data class RequestSubscriptionPropsByPlatforms( /** @@ -710,18 +1861,80 @@ public data class RequestSubscriptionPropsByPlatforms( /** * iOS-specific subscription parameters */ - val ios: RequestPurchaseIosProps? = null -) + val ios: RequestSubscriptionIosProps? = null +) { + companion object { + fun fromJson(json: Map): RequestSubscriptionPropsByPlatforms { + return RequestSubscriptionPropsByPlatforms( + android = (json["android"] as Map?)?.let { RequestSubscriptionAndroidProps.fromJson(it) }, + ios = (json["ios"] as Map?)?.let { RequestSubscriptionIosProps.fromJson(it) }, + ) + } + } + + fun toJson(): Map = mapOf( + "android" to android?.toJson(), + "ios" to ios?.toJson(), + ) +} // MARK: - Unions -public sealed interface Product +public sealed interface Product { + fun toJson(): Map + + companion object { + fun fromJson(json: Map): Product { + return when (json["__typename"] as String?) { + "ProductAndroid" -> ProductAndroid.fromJson(json) + "ProductIOS" -> ProductIOS.fromJson(json) + else -> throw IllegalArgumentException("Unknown __typename for Product: ${json["__typename"]}") + } + } + } +} -public sealed interface ProductSubscription +public sealed interface ProductSubscription { + fun toJson(): Map + + companion object { + fun fromJson(json: Map): ProductSubscription { + return when (json["__typename"] as String?) { + "ProductSubscriptionAndroid" -> ProductSubscriptionAndroid.fromJson(json) + "ProductSubscriptionIOS" -> ProductSubscriptionIOS.fromJson(json) + else -> throw IllegalArgumentException("Unknown __typename for ProductSubscription: ${json["__typename"]}") + } + } + } +} -public sealed interface Purchase +public sealed interface Purchase { + fun toJson(): Map + + companion object { + fun fromJson(json: Map): Purchase { + return when (json["__typename"] as String?) { + "PurchaseAndroid" -> PurchaseAndroid.fromJson(json) + "PurchaseIOS" -> PurchaseIOS.fromJson(json) + else -> throw IllegalArgumentException("Unknown __typename for Purchase: ${json["__typename"]}") + } + } + } +} -public sealed interface ReceiptValidationResult +public sealed interface ReceiptValidationResult { + fun toJson(): Map + + companion object { + fun fromJson(json: Map): ReceiptValidationResult { + return when (json["__typename"] as String?) { + "ReceiptValidationResultAndroid" -> ReceiptValidationResultAndroid.fromJson(json) + "ReceiptValidationResultIOS" -> ReceiptValidationResultIOS.fromJson(json) + else -> throw IllegalArgumentException("Unknown __typename for ReceiptValidationResult: ${json["__typename"]}") + } + } + } +} // MARK: - Root Operations diff --git a/src/generated/Types.swift b/src/generated/Types.swift index 819dd3a..079a6c8 100644 --- a/src/generated/Types.swift +++ b/src/generated/Types.swift @@ -50,6 +50,11 @@ public enum IapEvent: String, Codable, CaseIterable { case promotedProductIos = "PROMOTED_PRODUCT_IOS" } +public enum IapPlatform: String, Codable, CaseIterable { + case ios = "IOS" + case android = "ANDROID" +} + public enum PaymentModeIOS: String, Codable, CaseIterable { case empty = "EMPTY" case freeTrial = "FREE_TRIAL" @@ -57,11 +62,6 @@ public enum PaymentModeIOS: String, Codable, CaseIterable { case payUpFront = "PAY_UP_FRONT" } -public enum Platform: String, Codable, CaseIterable { - case ios = "IOS" - case android = "ANDROID" -} - public enum ProductQueryType: String, Codable, CaseIterable { case inApp = "IN_APP" case subs = "SUBS" @@ -111,7 +111,7 @@ public protocol ProductCommon: Codable { var displayName: String? { get } var displayPrice: String { get } var id: String { get } - var platform: Platform { get } + var platform: IapPlatform { get } var price: Double? { get } var title: String { get } var type: ProductType { get } @@ -121,7 +121,7 @@ public protocol PurchaseCommon: Codable { var id: String { get } var ids: [String]? { get } var isAutoRenewing: Bool { get } - var platform: Platform { get } + var platform: IapPlatform { get } var productId: String { get } var purchaseState: PurchaseState { get } /// Unified purchase token (iOS JWS, Android purchaseToken) @@ -218,7 +218,7 @@ public struct ProductAndroid: Codable, ProductCommon { public var id: String public var nameAndroid: String public var oneTimePurchaseOfferDetailsAndroid: ProductAndroidOneTimePurchaseOfferDetail? - public var platform: Platform + public var platform: IapPlatform public var price: Double? public var subscriptionOfferDetailsAndroid: [ProductSubscriptionAndroidOfferDetails]? public var title: String @@ -241,7 +241,7 @@ public struct ProductIOS: Codable, ProductCommon { public var id: String public var isFamilyShareableIOS: Bool public var jsonRepresentationIOS: String - public var platform: Platform + public var platform: IapPlatform public var price: Double? public var subscriptionInfoIOS: SubscriptionInfoIOS? public var title: String @@ -258,7 +258,7 @@ public struct ProductSubscriptionAndroid: Codable, ProductCommon { public var id: String public var nameAndroid: String public var oneTimePurchaseOfferDetailsAndroid: ProductAndroidOneTimePurchaseOfferDetail? - public var platform: Platform + public var platform: IapPlatform public var price: Double? public var subscriptionOfferDetailsAndroid: [ProductSubscriptionAndroidOfferDetails] public var title: String @@ -289,7 +289,7 @@ public struct ProductSubscriptionIOS: Codable, ProductCommon { public var introductoryPriceSubscriptionPeriodIOS: SubscriptionPeriodIOS? public var isFamilyShareableIOS: Bool public var jsonRepresentationIOS: String - public var platform: Platform + public var platform: IapPlatform public var price: Double? public var subscriptionInfoIOS: SubscriptionInfoIOS? public var subscriptionPeriodNumberIOS: String? @@ -310,7 +310,7 @@ public struct PurchaseAndroid: Codable, PurchaseCommon { public var obfuscatedAccountIdAndroid: String? public var obfuscatedProfileIdAndroid: String? public var packageNameAndroid: String? - public var platform: Platform + public var platform: IapPlatform public var productId: String public var purchaseState: PurchaseState public var purchaseToken: String? @@ -341,7 +341,7 @@ public struct PurchaseIOS: Codable, PurchaseCommon { public var originalTransactionDateIOS: Double? public var originalTransactionIdentifierIOS: String? public var ownershipTypeIOS: String? - public var platform: Platform + public var platform: IapPlatform public var productId: String public var purchaseState: PurchaseState public var purchaseToken: String? @@ -370,7 +370,7 @@ public struct ReceiptValidationResultAndroid: Codable { public var cancelDate: Double? public var cancelReason: String? public var deferredDate: Double? - public var deferredSku: Double? + public var deferredSku: String? public var freeTrialEndDate: Double public var gracePeriodEndDate: Double public var parentProductId: String @@ -481,7 +481,7 @@ public struct PurchaseInput: Codable { public var id: String public var ids: [String]? public var isAutoRenewing: Bool - public var platform: Platform + public var platform: IapPlatform public var productId: String public var purchaseState: PurchaseState public var purchaseToken: String? @@ -586,7 +586,7 @@ public struct RequestSubscriptionPropsByPlatforms: Codable { /// Android-specific subscription parameters public var android: RequestSubscriptionAndroidProps? /// iOS-specific subscription parameters - public var ios: RequestPurchaseIosProps? + public var ios: RequestSubscriptionIosProps? } // MARK: - Unions diff --git a/src/generated/types.dart b/src/generated/types.dart index 69b1d3b..c456f79 100644 --- a/src/generated/types.dart +++ b/src/generated/types.dart @@ -10,128 +10,466 @@ import 'dart:async'; // MARK: - Enums enum ErrorCode { - unknown('UNKNOWN'), - userCancelled('USER_CANCELLED'), - userError('USER_ERROR'), - itemUnavailable('ITEM_UNAVAILABLE'), - remoteError('REMOTE_ERROR'), - networkError('NETWORK_ERROR'), - serviceError('SERVICE_ERROR'), - receiptFailed('RECEIPT_FAILED'), - receiptFinished('RECEIPT_FINISHED'), - receiptFinishedFailed('RECEIPT_FINISHED_FAILED'), - notPrepared('NOT_PREPARED'), - notEnded('NOT_ENDED'), - alreadyOwned('ALREADY_OWNED'), - developerError('DEVELOPER_ERROR'), - billingResponseJsonParseError('BILLING_RESPONSE_JSON_PARSE_ERROR'), - deferredPayment('DEFERRED_PAYMENT'), - interrupted('INTERRUPTED'), - iapNotAvailable('IAP_NOT_AVAILABLE'), - purchaseError('PURCHASE_ERROR'), - syncError('SYNC_ERROR'), - transactionValidationFailed('TRANSACTION_VALIDATION_FAILED'), - activityUnavailable('ACTIVITY_UNAVAILABLE'), - alreadyPrepared('ALREADY_PREPARED'), - pending('PENDING'), - connectionClosed('CONNECTION_CLOSED'), - initConnection('INIT_CONNECTION'), - serviceDisconnected('SERVICE_DISCONNECTED'), - queryProduct('QUERY_PRODUCT'), - skuNotFound('SKU_NOT_FOUND'), - skuOfferMismatch('SKU_OFFER_MISMATCH'), - itemNotOwned('ITEM_NOT_OWNED'), - billingUnavailable('BILLING_UNAVAILABLE'), - featureNotSupported('FEATURE_NOT_SUPPORTED'), - emptySkuList('EMPTY_SKU_LIST'); + Unknown('UNKNOWN'), + UserCancelled('USER_CANCELLED'), + UserError('USER_ERROR'), + ItemUnavailable('ITEM_UNAVAILABLE'), + RemoteError('REMOTE_ERROR'), + NetworkError('NETWORK_ERROR'), + ServiceError('SERVICE_ERROR'), + ReceiptFailed('RECEIPT_FAILED'), + ReceiptFinished('RECEIPT_FINISHED'), + ReceiptFinishedFailed('RECEIPT_FINISHED_FAILED'), + NotPrepared('NOT_PREPARED'), + NotEnded('NOT_ENDED'), + AlreadyOwned('ALREADY_OWNED'), + DeveloperError('DEVELOPER_ERROR'), + BillingResponseJsonParseError('BILLING_RESPONSE_JSON_PARSE_ERROR'), + DeferredPayment('DEFERRED_PAYMENT'), + Interrupted('INTERRUPTED'), + IapNotAvailable('IAP_NOT_AVAILABLE'), + PurchaseError('PURCHASE_ERROR'), + SyncError('SYNC_ERROR'), + TransactionValidationFailed('TRANSACTION_VALIDATION_FAILED'), + ActivityUnavailable('ACTIVITY_UNAVAILABLE'), + AlreadyPrepared('ALREADY_PREPARED'), + Pending('PENDING'), + ConnectionClosed('CONNECTION_CLOSED'), + InitConnection('INIT_CONNECTION'), + ServiceDisconnected('SERVICE_DISCONNECTED'), + QueryProduct('QUERY_PRODUCT'), + SkuNotFound('SKU_NOT_FOUND'), + SkuOfferMismatch('SKU_OFFER_MISMATCH'), + ItemNotOwned('ITEM_NOT_OWNED'), + BillingUnavailable('BILLING_UNAVAILABLE'), + FeatureNotSupported('FEATURE_NOT_SUPPORTED'), + EmptySkuList('EMPTY_SKU_LIST'); const ErrorCode(this.value); final String value; + + factory ErrorCode.fromJson(String value) { + switch (value) { + case 'UNKNOWN': + return ErrorCode.Unknown; + case 'Unknown': + return ErrorCode.Unknown; + case 'USER_CANCELLED': + return ErrorCode.UserCancelled; + case 'UserCancelled': + return ErrorCode.UserCancelled; + case 'USER_ERROR': + return ErrorCode.UserError; + case 'UserError': + return ErrorCode.UserError; + case 'ITEM_UNAVAILABLE': + return ErrorCode.ItemUnavailable; + case 'ItemUnavailable': + return ErrorCode.ItemUnavailable; + case 'REMOTE_ERROR': + return ErrorCode.RemoteError; + case 'RemoteError': + return ErrorCode.RemoteError; + case 'NETWORK_ERROR': + return ErrorCode.NetworkError; + case 'NetworkError': + return ErrorCode.NetworkError; + case 'SERVICE_ERROR': + return ErrorCode.ServiceError; + case 'ServiceError': + return ErrorCode.ServiceError; + case 'RECEIPT_FAILED': + return ErrorCode.ReceiptFailed; + case 'ReceiptFailed': + return ErrorCode.ReceiptFailed; + case 'RECEIPT_FINISHED': + return ErrorCode.ReceiptFinished; + case 'ReceiptFinished': + return ErrorCode.ReceiptFinished; + case 'RECEIPT_FINISHED_FAILED': + return ErrorCode.ReceiptFinishedFailed; + case 'ReceiptFinishedFailed': + return ErrorCode.ReceiptFinishedFailed; + case 'NOT_PREPARED': + return ErrorCode.NotPrepared; + case 'NotPrepared': + return ErrorCode.NotPrepared; + case 'NOT_ENDED': + return ErrorCode.NotEnded; + case 'NotEnded': + return ErrorCode.NotEnded; + case 'ALREADY_OWNED': + return ErrorCode.AlreadyOwned; + case 'AlreadyOwned': + return ErrorCode.AlreadyOwned; + case 'DEVELOPER_ERROR': + return ErrorCode.DeveloperError; + case 'DeveloperError': + return ErrorCode.DeveloperError; + case 'BILLING_RESPONSE_JSON_PARSE_ERROR': + return ErrorCode.BillingResponseJsonParseError; + case 'BillingResponseJsonParseError': + return ErrorCode.BillingResponseJsonParseError; + case 'DEFERRED_PAYMENT': + return ErrorCode.DeferredPayment; + case 'DeferredPayment': + return ErrorCode.DeferredPayment; + case 'INTERRUPTED': + return ErrorCode.Interrupted; + case 'Interrupted': + return ErrorCode.Interrupted; + case 'IAP_NOT_AVAILABLE': + return ErrorCode.IapNotAvailable; + case 'IapNotAvailable': + return ErrorCode.IapNotAvailable; + case 'PURCHASE_ERROR': + return ErrorCode.PurchaseError; + case 'PurchaseError': + return ErrorCode.PurchaseError; + case 'SYNC_ERROR': + return ErrorCode.SyncError; + case 'SyncError': + return ErrorCode.SyncError; + case 'TRANSACTION_VALIDATION_FAILED': + return ErrorCode.TransactionValidationFailed; + case 'TransactionValidationFailed': + return ErrorCode.TransactionValidationFailed; + case 'ACTIVITY_UNAVAILABLE': + return ErrorCode.ActivityUnavailable; + case 'ActivityUnavailable': + return ErrorCode.ActivityUnavailable; + case 'ALREADY_PREPARED': + return ErrorCode.AlreadyPrepared; + case 'AlreadyPrepared': + return ErrorCode.AlreadyPrepared; + case 'PENDING': + return ErrorCode.Pending; + case 'Pending': + return ErrorCode.Pending; + case 'CONNECTION_CLOSED': + return ErrorCode.ConnectionClosed; + case 'ConnectionClosed': + return ErrorCode.ConnectionClosed; + case 'INIT_CONNECTION': + return ErrorCode.InitConnection; + case 'InitConnection': + return ErrorCode.InitConnection; + case 'SERVICE_DISCONNECTED': + return ErrorCode.ServiceDisconnected; + case 'ServiceDisconnected': + return ErrorCode.ServiceDisconnected; + case 'QUERY_PRODUCT': + return ErrorCode.QueryProduct; + case 'QueryProduct': + return ErrorCode.QueryProduct; + case 'SKU_NOT_FOUND': + return ErrorCode.SkuNotFound; + case 'SkuNotFound': + return ErrorCode.SkuNotFound; + case 'SKU_OFFER_MISMATCH': + return ErrorCode.SkuOfferMismatch; + case 'SkuOfferMismatch': + return ErrorCode.SkuOfferMismatch; + case 'ITEM_NOT_OWNED': + return ErrorCode.ItemNotOwned; + case 'ItemNotOwned': + return ErrorCode.ItemNotOwned; + case 'BILLING_UNAVAILABLE': + return ErrorCode.BillingUnavailable; + case 'BillingUnavailable': + return ErrorCode.BillingUnavailable; + case 'FEATURE_NOT_SUPPORTED': + return ErrorCode.FeatureNotSupported; + case 'FeatureNotSupported': + return ErrorCode.FeatureNotSupported; + case 'EMPTY_SKU_LIST': + return ErrorCode.EmptySkuList; + case 'EmptySkuList': + return ErrorCode.EmptySkuList; + } + throw ArgumentError('Unknown ErrorCode value: $value'); + } + + String toJson() => value; } enum IapEvent { - purchaseUpdated('PURCHASE_UPDATED'), - purchaseError('PURCHASE_ERROR'), - promotedProductIos('PROMOTED_PRODUCT_IOS'); + PurchaseUpdated('PURCHASE_UPDATED'), + PurchaseError('PURCHASE_ERROR'), + PromotedProductIOS('PROMOTED_PRODUCT_IOS'); const IapEvent(this.value); final String value; + + factory IapEvent.fromJson(String value) { + switch (value) { + case 'PURCHASE_UPDATED': + return IapEvent.PurchaseUpdated; + case 'PurchaseUpdated': + return IapEvent.PurchaseUpdated; + case 'PURCHASE_ERROR': + return IapEvent.PurchaseError; + case 'PurchaseError': + return IapEvent.PurchaseError; + case 'PROMOTED_PRODUCT_IOS': + return IapEvent.PromotedProductIOS; + case 'PromotedProductIOS': + return IapEvent.PromotedProductIOS; + } + throw ArgumentError('Unknown IapEvent value: $value'); + } + + String toJson() => value; } -enum PaymentModeIOS { - empty('EMPTY'), - freeTrial('FREE_TRIAL'), - payAsYouGo('PAY_AS_YOU_GO'), - payUpFront('PAY_UP_FRONT'); +enum IapPlatform { + IOS('IOS'), + Android('ANDROID'); - const PaymentModeIOS(this.value); + const IapPlatform(this.value); final String value; + + factory IapPlatform.fromJson(String value) { + switch (value) { + case 'IOS': + return IapPlatform.IOS; + case 'ANDROID': + return IapPlatform.Android; + case 'Android': + return IapPlatform.Android; + } + throw ArgumentError('Unknown IapPlatform value: $value'); + } + + String toJson() => value; } -enum Platform { - ios('IOS'), - android('ANDROID'); +enum PaymentModeIOS { + Empty('EMPTY'), + FreeTrial('FREE_TRIAL'), + PayAsYouGo('PAY_AS_YOU_GO'), + PayUpFront('PAY_UP_FRONT'); - const Platform(this.value); + const PaymentModeIOS(this.value); final String value; + + factory PaymentModeIOS.fromJson(String value) { + switch (value) { + case 'EMPTY': + return PaymentModeIOS.Empty; + case 'Empty': + return PaymentModeIOS.Empty; + case 'FREE_TRIAL': + return PaymentModeIOS.FreeTrial; + case 'FreeTrial': + return PaymentModeIOS.FreeTrial; + case 'PAY_AS_YOU_GO': + return PaymentModeIOS.PayAsYouGo; + case 'PayAsYouGo': + return PaymentModeIOS.PayAsYouGo; + case 'PAY_UP_FRONT': + return PaymentModeIOS.PayUpFront; + case 'PayUpFront': + return PaymentModeIOS.PayUpFront; + } + throw ArgumentError('Unknown PaymentModeIOS value: $value'); + } + + String toJson() => value; } enum ProductQueryType { - inApp('IN_APP'), - subs('SUBS'), - all('ALL'); + InApp('IN_APP'), + Subs('SUBS'), + All('ALL'); const ProductQueryType(this.value); final String value; + + factory ProductQueryType.fromJson(String value) { + switch (value) { + case 'IN_APP': + return ProductQueryType.InApp; + case 'InApp': + return ProductQueryType.InApp; + case 'SUBS': + return ProductQueryType.Subs; + case 'Subs': + return ProductQueryType.Subs; + case 'ALL': + return ProductQueryType.All; + case 'All': + return ProductQueryType.All; + } + throw ArgumentError('Unknown ProductQueryType value: $value'); + } + + String toJson() => value; } enum ProductType { - inApp('IN_APP'), - subs('SUBS'); + InApp('IN_APP'), + Subs('SUBS'); const ProductType(this.value); final String value; + + factory ProductType.fromJson(String value) { + switch (value) { + case 'IN_APP': + return ProductType.InApp; + case 'InApp': + return ProductType.InApp; + case 'SUBS': + return ProductType.Subs; + case 'Subs': + return ProductType.Subs; + } + throw ArgumentError('Unknown ProductType value: $value'); + } + + String toJson() => value; } enum ProductTypeIOS { - consumable('CONSUMABLE'), - nonConsumable('NON_CONSUMABLE'), - autoRenewableSubscription('AUTO_RENEWABLE_SUBSCRIPTION'), - nonRenewingSubscription('NON_RENEWING_SUBSCRIPTION'); + Consumable('CONSUMABLE'), + NonConsumable('NON_CONSUMABLE'), + AutoRenewableSubscription('AUTO_RENEWABLE_SUBSCRIPTION'), + NonRenewingSubscription('NON_RENEWING_SUBSCRIPTION'); const ProductTypeIOS(this.value); final String value; + + factory ProductTypeIOS.fromJson(String value) { + switch (value) { + case 'CONSUMABLE': + return ProductTypeIOS.Consumable; + case 'Consumable': + return ProductTypeIOS.Consumable; + case 'NON_CONSUMABLE': + return ProductTypeIOS.NonConsumable; + case 'NonConsumable': + return ProductTypeIOS.NonConsumable; + case 'AUTO_RENEWABLE_SUBSCRIPTION': + return ProductTypeIOS.AutoRenewableSubscription; + case 'AutoRenewableSubscription': + return ProductTypeIOS.AutoRenewableSubscription; + case 'NON_RENEWING_SUBSCRIPTION': + return ProductTypeIOS.NonRenewingSubscription; + case 'NonRenewingSubscription': + return ProductTypeIOS.NonRenewingSubscription; + } + throw ArgumentError('Unknown ProductTypeIOS value: $value'); + } + + String toJson() => value; } enum PurchaseState { - pending('PENDING'), - purchased('PURCHASED'), - failed('FAILED'), - restored('RESTORED'), - deferred('DEFERRED'), - unknown('UNKNOWN'); + Pending('PENDING'), + Purchased('PURCHASED'), + Failed('FAILED'), + Restored('RESTORED'), + Deferred('DEFERRED'), + Unknown('UNKNOWN'); const PurchaseState(this.value); final String value; + + factory PurchaseState.fromJson(String value) { + switch (value) { + case 'PENDING': + return PurchaseState.Pending; + case 'Pending': + return PurchaseState.Pending; + case 'PURCHASED': + return PurchaseState.Purchased; + case 'Purchased': + return PurchaseState.Purchased; + case 'FAILED': + return PurchaseState.Failed; + case 'Failed': + return PurchaseState.Failed; + case 'RESTORED': + return PurchaseState.Restored; + case 'Restored': + return PurchaseState.Restored; + case 'DEFERRED': + return PurchaseState.Deferred; + case 'Deferred': + return PurchaseState.Deferred; + case 'UNKNOWN': + return PurchaseState.Unknown; + case 'Unknown': + return PurchaseState.Unknown; + } + throw ArgumentError('Unknown PurchaseState value: $value'); + } + + String toJson() => value; } enum SubscriptionOfferTypeIOS { - introductory('INTRODUCTORY'), - promotional('PROMOTIONAL'); + Introductory('INTRODUCTORY'), + Promotional('PROMOTIONAL'); const SubscriptionOfferTypeIOS(this.value); final String value; + + factory SubscriptionOfferTypeIOS.fromJson(String value) { + switch (value) { + case 'INTRODUCTORY': + return SubscriptionOfferTypeIOS.Introductory; + case 'Introductory': + return SubscriptionOfferTypeIOS.Introductory; + case 'PROMOTIONAL': + return SubscriptionOfferTypeIOS.Promotional; + case 'Promotional': + return SubscriptionOfferTypeIOS.Promotional; + } + throw ArgumentError('Unknown SubscriptionOfferTypeIOS value: $value'); + } + + String toJson() => value; } enum SubscriptionPeriodIOS { - day('DAY'), - week('WEEK'), - month('MONTH'), - year('YEAR'), - empty('EMPTY'); + Day('DAY'), + Week('WEEK'), + Month('MONTH'), + Year('YEAR'), + Empty('EMPTY'); const SubscriptionPeriodIOS(this.value); final String value; + + factory SubscriptionPeriodIOS.fromJson(String value) { + switch (value) { + case 'DAY': + return SubscriptionPeriodIOS.Day; + case 'Day': + return SubscriptionPeriodIOS.Day; + case 'WEEK': + return SubscriptionPeriodIOS.Week; + case 'Week': + return SubscriptionPeriodIOS.Week; + case 'MONTH': + return SubscriptionPeriodIOS.Month; + case 'Month': + return SubscriptionPeriodIOS.Month; + case 'YEAR': + return SubscriptionPeriodIOS.Year; + case 'Year': + return SubscriptionPeriodIOS.Year; + case 'EMPTY': + return SubscriptionPeriodIOS.Empty; + case 'Empty': + return SubscriptionPeriodIOS.Empty; + } + throw ArgumentError('Unknown SubscriptionPeriodIOS value: $value'); + } + + String toJson() => value; } // MARK: - Interfaces @@ -143,7 +481,7 @@ abstract class ProductCommon { String? get displayName; String get displayPrice; String get id; - Platform get platform; + IapPlatform get platform; double? get price; String get title; ProductType get type; @@ -153,7 +491,7 @@ abstract class PurchaseCommon { String get id; List? get ids; bool get isAutoRenewing; - Platform get platform; + IapPlatform get platform; String get productId; PurchaseState get purchaseState; /// Unified purchase token (iOS JWS, Android purchaseToken) @@ -188,6 +526,37 @@ class ActiveSubscription { final double transactionDate; final String transactionId; final bool? willExpireSoon; + + factory ActiveSubscription.fromJson(Map json) { + return ActiveSubscription( + autoRenewingAndroid: json['autoRenewingAndroid'] as bool?, + daysUntilExpirationIOS: (json['daysUntilExpirationIOS'] as num?)?.toDouble(), + environmentIOS: json['environmentIOS'] as String?, + expirationDateIOS: (json['expirationDateIOS'] as num?)?.toDouble(), + isActive: json['isActive'] as bool, + productId: json['productId'] as String, + purchaseToken: json['purchaseToken'] as String?, + transactionDate: (json['transactionDate'] as num).toDouble(), + transactionId: json['transactionId'] as String, + willExpireSoon: json['willExpireSoon'] as bool?, + ); + } + + Map toJson() { + return { + '__typename': 'ActiveSubscription', + 'autoRenewingAndroid': autoRenewingAndroid, + 'daysUntilExpirationIOS': daysUntilExpirationIOS, + 'environmentIOS': environmentIOS, + 'expirationDateIOS': expirationDateIOS, + 'isActive': isActive, + 'productId': productId, + 'purchaseToken': purchaseToken, + 'transactionDate': transactionDate, + 'transactionId': transactionId, + 'willExpireSoon': willExpireSoon, + }; + } } class AppTransaction { @@ -220,6 +589,43 @@ class AppTransaction { final double originalPurchaseDate; final double? preorderDate; final double signedDate; + + factory AppTransaction.fromJson(Map json) { + return AppTransaction( + appId: (json['appId'] as num).toDouble(), + appTransactionId: json['appTransactionId'] as String?, + appVersion: json['appVersion'] as String, + appVersionId: (json['appVersionId'] as num).toDouble(), + bundleId: json['bundleId'] as String, + deviceVerification: json['deviceVerification'] as String, + deviceVerificationNonce: json['deviceVerificationNonce'] as String, + environment: json['environment'] as String, + originalAppVersion: json['originalAppVersion'] as String, + originalPlatform: json['originalPlatform'] as String?, + originalPurchaseDate: (json['originalPurchaseDate'] as num).toDouble(), + preorderDate: (json['preorderDate'] as num?)?.toDouble(), + signedDate: (json['signedDate'] as num).toDouble(), + ); + } + + Map toJson() { + return { + '__typename': 'AppTransaction', + 'appId': appId, + 'appTransactionId': appTransactionId, + 'appVersion': appVersion, + 'appVersionId': appVersionId, + 'bundleId': bundleId, + 'deviceVerification': deviceVerification, + 'deviceVerificationNonce': deviceVerificationNonce, + 'environment': environment, + 'originalAppVersion': originalAppVersion, + 'originalPlatform': originalPlatform, + 'originalPurchaseDate': originalPurchaseDate, + 'preorderDate': preorderDate, + 'signedDate': signedDate, + }; + } } class DiscountIOS { @@ -242,6 +648,33 @@ class DiscountIOS { final double priceAmount; final String subscriptionPeriod; final String type; + + factory DiscountIOS.fromJson(Map json) { + return DiscountIOS( + identifier: json['identifier'] as String, + localizedPrice: json['localizedPrice'] as String?, + numberOfPeriods: json['numberOfPeriods'] as int, + paymentMode: PaymentModeIOS.fromJson(json['paymentMode'] as String), + price: json['price'] as String, + priceAmount: (json['priceAmount'] as num).toDouble(), + subscriptionPeriod: json['subscriptionPeriod'] as String, + type: json['type'] as String, + ); + } + + Map toJson() { + return { + '__typename': 'DiscountIOS', + 'identifier': identifier, + 'localizedPrice': localizedPrice, + 'numberOfPeriods': numberOfPeriods, + 'paymentMode': paymentMode.toJson(), + 'price': price, + 'priceAmount': priceAmount, + 'subscriptionPeriod': subscriptionPeriod, + 'type': type, + }; + } } class DiscountOfferIOS { @@ -268,6 +701,27 @@ class DiscountOfferIOS { final String signature; /// Timestamp of discount offer final double timestamp; + + factory DiscountOfferIOS.fromJson(Map json) { + return DiscountOfferIOS( + identifier: json['identifier'] as String, + keyIdentifier: json['keyIdentifier'] as String, + nonce: json['nonce'] as String, + signature: json['signature'] as String, + timestamp: (json['timestamp'] as num).toDouble(), + ); + } + + Map toJson() { + return { + '__typename': 'DiscountOfferIOS', + 'identifier': identifier, + 'keyIdentifier': keyIdentifier, + 'nonce': nonce, + 'signature': signature, + 'timestamp': timestamp, + }; + } } class EntitlementIOS { @@ -280,6 +734,23 @@ class EntitlementIOS { final String jsonRepresentation; final String sku; final String transactionId; + + factory EntitlementIOS.fromJson(Map json) { + return EntitlementIOS( + jsonRepresentation: json['jsonRepresentation'] as String, + sku: json['sku'] as String, + transactionId: json['transactionId'] as String, + ); + } + + Map toJson() { + return { + '__typename': 'EntitlementIOS', + 'jsonRepresentation': jsonRepresentation, + 'sku': sku, + 'transactionId': transactionId, + }; + } } class FetchProductsResult { @@ -290,6 +761,21 @@ class FetchProductsResult { final List? products; final List? subscriptions; + + factory FetchProductsResult.fromJson(Map json) { + return FetchProductsResult( + products: (json['products'] as List?) == null ? null : (json['products'] as List?)!.map((e) => Product.fromJson(e as Map)).toList(), + subscriptions: (json['subscriptions'] as List?) == null ? null : (json['subscriptions'] as List?)!.map((e) => ProductSubscription.fromJson(e as Map)).toList(), + ); + } + + Map toJson() { + return { + '__typename': 'FetchProductsResult', + 'products': products == null ? null : products!.map((e) => e.toJson()).toList(), + 'subscriptions': subscriptions == null ? null : subscriptions!.map((e) => e.toJson()).toList(), + }; + } } class PricingPhaseAndroid { @@ -308,6 +794,29 @@ class PricingPhaseAndroid { final String priceAmountMicros; final String priceCurrencyCode; final int recurrenceMode; + + factory PricingPhaseAndroid.fromJson(Map json) { + return PricingPhaseAndroid( + billingCycleCount: json['billingCycleCount'] as int, + billingPeriod: json['billingPeriod'] as String, + formattedPrice: json['formattedPrice'] as String, + priceAmountMicros: json['priceAmountMicros'] as String, + priceCurrencyCode: json['priceCurrencyCode'] as String, + recurrenceMode: json['recurrenceMode'] as int, + ); + } + + Map toJson() { + return { + '__typename': 'PricingPhaseAndroid', + 'billingCycleCount': billingCycleCount, + 'billingPeriod': billingPeriod, + 'formattedPrice': formattedPrice, + 'priceAmountMicros': priceAmountMicros, + 'priceCurrencyCode': priceCurrencyCode, + 'recurrenceMode': recurrenceMode, + }; + } } class PricingPhasesAndroid { @@ -316,9 +825,22 @@ class PricingPhasesAndroid { }); final List pricingPhaseList; + + factory PricingPhasesAndroid.fromJson(Map json) { + return PricingPhasesAndroid( + pricingPhaseList: (json['pricingPhaseList'] as List).map((e) => PricingPhaseAndroid.fromJson(e as Map)).toList(), + ); + } + + Map toJson() { + return { + '__typename': 'PricingPhasesAndroid', + 'pricingPhaseList': pricingPhaseList.map((e) => e.toJson()).toList(), + }; + } } -class ProductAndroid implements ProductCommon, Product { +class ProductAndroid extends Product implements ProductCommon { const ProductAndroid({ required this.currency, this.debugDescription, @@ -343,11 +865,49 @@ class ProductAndroid implements ProductCommon, Product { final String id; final String nameAndroid; final ProductAndroidOneTimePurchaseOfferDetail? oneTimePurchaseOfferDetailsAndroid; - final Platform platform; + final IapPlatform platform; final double? price; final List? subscriptionOfferDetailsAndroid; final String title; final ProductType type; + + factory ProductAndroid.fromJson(Map json) { + return ProductAndroid( + currency: json['currency'] as String, + debugDescription: json['debugDescription'] as String?, + description: json['description'] as String, + displayName: json['displayName'] as String?, + displayPrice: json['displayPrice'] as String, + id: json['id'] as String, + nameAndroid: json['nameAndroid'] as String, + oneTimePurchaseOfferDetailsAndroid: json['oneTimePurchaseOfferDetailsAndroid'] != null ? ProductAndroidOneTimePurchaseOfferDetail.fromJson(json['oneTimePurchaseOfferDetailsAndroid'] as Map) : null, + platform: IapPlatform.fromJson(json['platform'] as String), + price: (json['price'] as num?)?.toDouble(), + subscriptionOfferDetailsAndroid: (json['subscriptionOfferDetailsAndroid'] as List?) == null ? null : (json['subscriptionOfferDetailsAndroid'] as List?)!.map((e) => ProductSubscriptionAndroidOfferDetails.fromJson(e as Map)).toList(), + title: json['title'] as String, + type: ProductType.fromJson(json['type'] as String), + ); + } + + @override + Map toJson() { + return { + '__typename': 'ProductAndroid', + 'currency': currency, + 'debugDescription': debugDescription, + 'description': description, + 'displayName': displayName, + 'displayPrice': displayPrice, + 'id': id, + 'nameAndroid': nameAndroid, + 'oneTimePurchaseOfferDetailsAndroid': oneTimePurchaseOfferDetailsAndroid?.toJson(), + 'platform': platform.toJson(), + 'price': price, + 'subscriptionOfferDetailsAndroid': subscriptionOfferDetailsAndroid == null ? null : subscriptionOfferDetailsAndroid!.map((e) => e.toJson()).toList(), + 'title': title, + 'type': type.toJson(), + }; + } } class ProductAndroidOneTimePurchaseOfferDetail { @@ -360,9 +920,26 @@ class ProductAndroidOneTimePurchaseOfferDetail { final String formattedPrice; final String priceAmountMicros; final String priceCurrencyCode; + + factory ProductAndroidOneTimePurchaseOfferDetail.fromJson(Map json) { + return ProductAndroidOneTimePurchaseOfferDetail( + formattedPrice: json['formattedPrice'] as String, + priceAmountMicros: json['priceAmountMicros'] as String, + priceCurrencyCode: json['priceCurrencyCode'] as String, + ); + } + + Map toJson() { + return { + '__typename': 'ProductAndroidOneTimePurchaseOfferDetail', + 'formattedPrice': formattedPrice, + 'priceAmountMicros': priceAmountMicros, + 'priceCurrencyCode': priceCurrencyCode, + }; + } } -class ProductIOS implements ProductCommon, Product { +class ProductIOS extends Product implements ProductCommon { const ProductIOS({ required this.currency, this.debugDescription, @@ -390,15 +967,57 @@ class ProductIOS implements ProductCommon, Product { final String id; final bool isFamilyShareableIOS; final String jsonRepresentationIOS; - final Platform platform; + final IapPlatform platform; final double? price; final SubscriptionInfoIOS? subscriptionInfoIOS; final String title; final ProductType type; final ProductTypeIOS typeIOS; + + factory ProductIOS.fromJson(Map json) { + return ProductIOS( + currency: json['currency'] as String, + debugDescription: json['debugDescription'] as String?, + description: json['description'] as String, + displayName: json['displayName'] as String?, + displayNameIOS: json['displayNameIOS'] as String, + displayPrice: json['displayPrice'] as String, + id: json['id'] as String, + isFamilyShareableIOS: json['isFamilyShareableIOS'] as bool, + jsonRepresentationIOS: json['jsonRepresentationIOS'] as String, + platform: IapPlatform.fromJson(json['platform'] as String), + price: (json['price'] as num?)?.toDouble(), + subscriptionInfoIOS: json['subscriptionInfoIOS'] != null ? SubscriptionInfoIOS.fromJson(json['subscriptionInfoIOS'] as Map) : null, + title: json['title'] as String, + type: ProductType.fromJson(json['type'] as String), + typeIOS: ProductTypeIOS.fromJson(json['typeIOS'] as String), + ); + } + + @override + Map toJson() { + return { + '__typename': 'ProductIOS', + 'currency': currency, + 'debugDescription': debugDescription, + 'description': description, + 'displayName': displayName, + 'displayNameIOS': displayNameIOS, + 'displayPrice': displayPrice, + 'id': id, + 'isFamilyShareableIOS': isFamilyShareableIOS, + 'jsonRepresentationIOS': jsonRepresentationIOS, + 'platform': platform.toJson(), + 'price': price, + 'subscriptionInfoIOS': subscriptionInfoIOS?.toJson(), + 'title': title, + 'type': type.toJson(), + 'typeIOS': typeIOS.toJson(), + }; + } } -class ProductSubscriptionAndroid implements ProductCommon, ProductSubscription { +class ProductSubscriptionAndroid extends ProductSubscription implements ProductCommon { const ProductSubscriptionAndroid({ required this.currency, this.debugDescription, @@ -423,11 +1042,49 @@ class ProductSubscriptionAndroid implements ProductCommon, ProductSubscription { final String id; final String nameAndroid; final ProductAndroidOneTimePurchaseOfferDetail? oneTimePurchaseOfferDetailsAndroid; - final Platform platform; + final IapPlatform platform; final double? price; final List subscriptionOfferDetailsAndroid; final String title; final ProductType type; + + factory ProductSubscriptionAndroid.fromJson(Map json) { + return ProductSubscriptionAndroid( + currency: json['currency'] as String, + debugDescription: json['debugDescription'] as String?, + description: json['description'] as String, + displayName: json['displayName'] as String?, + displayPrice: json['displayPrice'] as String, + id: json['id'] as String, + nameAndroid: json['nameAndroid'] as String, + oneTimePurchaseOfferDetailsAndroid: json['oneTimePurchaseOfferDetailsAndroid'] != null ? ProductAndroidOneTimePurchaseOfferDetail.fromJson(json['oneTimePurchaseOfferDetailsAndroid'] as Map) : null, + platform: IapPlatform.fromJson(json['platform'] as String), + price: (json['price'] as num?)?.toDouble(), + subscriptionOfferDetailsAndroid: (json['subscriptionOfferDetailsAndroid'] as List).map((e) => ProductSubscriptionAndroidOfferDetails.fromJson(e as Map)).toList(), + title: json['title'] as String, + type: ProductType.fromJson(json['type'] as String), + ); + } + + @override + Map toJson() { + return { + '__typename': 'ProductSubscriptionAndroid', + 'currency': currency, + 'debugDescription': debugDescription, + 'description': description, + 'displayName': displayName, + 'displayPrice': displayPrice, + 'id': id, + 'nameAndroid': nameAndroid, + 'oneTimePurchaseOfferDetailsAndroid': oneTimePurchaseOfferDetailsAndroid?.toJson(), + 'platform': platform.toJson(), + 'price': price, + 'subscriptionOfferDetailsAndroid': subscriptionOfferDetailsAndroid.map((e) => e.toJson()).toList(), + 'title': title, + 'type': type.toJson(), + }; + } } class ProductSubscriptionAndroidOfferDetails { @@ -444,9 +1101,30 @@ class ProductSubscriptionAndroidOfferDetails { final List offerTags; final String offerToken; final PricingPhasesAndroid pricingPhases; + + factory ProductSubscriptionAndroidOfferDetails.fromJson(Map json) { + return ProductSubscriptionAndroidOfferDetails( + basePlanId: json['basePlanId'] as String, + offerId: json['offerId'] as String?, + offerTags: (json['offerTags'] as List).map((e) => e as String).toList(), + offerToken: json['offerToken'] as String, + pricingPhases: PricingPhasesAndroid.fromJson(json['pricingPhases'] as Map), + ); + } + + Map toJson() { + return { + '__typename': 'ProductSubscriptionAndroidOfferDetails', + 'basePlanId': basePlanId, + 'offerId': offerId, + 'offerTags': offerTags.map((e) => e).toList(), + 'offerToken': offerToken, + 'pricingPhases': pricingPhases.toJson(), + }; + } } -class ProductSubscriptionIOS implements ProductCommon, ProductSubscription { +class ProductSubscriptionIOS extends ProductSubscription implements ProductCommon { const ProductSubscriptionIOS({ required this.currency, this.debugDescription, @@ -488,7 +1166,7 @@ class ProductSubscriptionIOS implements ProductCommon, ProductSubscription { final SubscriptionPeriodIOS? introductoryPriceSubscriptionPeriodIOS; final bool isFamilyShareableIOS; final String jsonRepresentationIOS; - final Platform platform; + final IapPlatform platform; final double? price; final SubscriptionInfoIOS? subscriptionInfoIOS; final String? subscriptionPeriodNumberIOS; @@ -496,9 +1174,67 @@ class ProductSubscriptionIOS implements ProductCommon, ProductSubscription { final String title; final ProductType type; final ProductTypeIOS typeIOS; + + factory ProductSubscriptionIOS.fromJson(Map json) { + return ProductSubscriptionIOS( + currency: json['currency'] as String, + debugDescription: json['debugDescription'] as String?, + description: json['description'] as String, + discountsIOS: (json['discountsIOS'] as List?) == null ? null : (json['discountsIOS'] as List?)!.map((e) => DiscountIOS.fromJson(e as Map)).toList(), + displayName: json['displayName'] as String?, + displayNameIOS: json['displayNameIOS'] as String, + displayPrice: json['displayPrice'] as String, + id: json['id'] as String, + introductoryPriceAsAmountIOS: json['introductoryPriceAsAmountIOS'] as String?, + introductoryPriceIOS: json['introductoryPriceIOS'] as String?, + introductoryPriceNumberOfPeriodsIOS: json['introductoryPriceNumberOfPeriodsIOS'] as String?, + introductoryPricePaymentModeIOS: json['introductoryPricePaymentModeIOS'] != null ? PaymentModeIOS.fromJson(json['introductoryPricePaymentModeIOS'] as String) : null, + introductoryPriceSubscriptionPeriodIOS: json['introductoryPriceSubscriptionPeriodIOS'] != null ? SubscriptionPeriodIOS.fromJson(json['introductoryPriceSubscriptionPeriodIOS'] as String) : null, + isFamilyShareableIOS: json['isFamilyShareableIOS'] as bool, + jsonRepresentationIOS: json['jsonRepresentationIOS'] as String, + platform: IapPlatform.fromJson(json['platform'] as String), + price: (json['price'] as num?)?.toDouble(), + subscriptionInfoIOS: json['subscriptionInfoIOS'] != null ? SubscriptionInfoIOS.fromJson(json['subscriptionInfoIOS'] as Map) : null, + subscriptionPeriodNumberIOS: json['subscriptionPeriodNumberIOS'] as String?, + subscriptionPeriodUnitIOS: json['subscriptionPeriodUnitIOS'] != null ? SubscriptionPeriodIOS.fromJson(json['subscriptionPeriodUnitIOS'] as String) : null, + title: json['title'] as String, + type: ProductType.fromJson(json['type'] as String), + typeIOS: ProductTypeIOS.fromJson(json['typeIOS'] as String), + ); + } + + @override + Map toJson() { + return { + '__typename': 'ProductSubscriptionIOS', + 'currency': currency, + 'debugDescription': debugDescription, + 'description': description, + 'discountsIOS': discountsIOS == null ? null : discountsIOS!.map((e) => e.toJson()).toList(), + 'displayName': displayName, + 'displayNameIOS': displayNameIOS, + 'displayPrice': displayPrice, + 'id': id, + 'introductoryPriceAsAmountIOS': introductoryPriceAsAmountIOS, + 'introductoryPriceIOS': introductoryPriceIOS, + 'introductoryPriceNumberOfPeriodsIOS': introductoryPriceNumberOfPeriodsIOS, + 'introductoryPricePaymentModeIOS': introductoryPricePaymentModeIOS?.toJson(), + 'introductoryPriceSubscriptionPeriodIOS': introductoryPriceSubscriptionPeriodIOS?.toJson(), + 'isFamilyShareableIOS': isFamilyShareableIOS, + 'jsonRepresentationIOS': jsonRepresentationIOS, + 'platform': platform.toJson(), + 'price': price, + 'subscriptionInfoIOS': subscriptionInfoIOS?.toJson(), + 'subscriptionPeriodNumberIOS': subscriptionPeriodNumberIOS, + 'subscriptionPeriodUnitIOS': subscriptionPeriodUnitIOS?.toJson(), + 'title': title, + 'type': type.toJson(), + 'typeIOS': typeIOS.toJson(), + }; + } } -class PurchaseAndroid implements PurchaseCommon, Purchase { +class PurchaseAndroid extends Purchase implements PurchaseCommon { const PurchaseAndroid({ this.autoRenewingAndroid, this.dataAndroid, @@ -529,13 +1265,59 @@ class PurchaseAndroid implements PurchaseCommon, Purchase { final String? obfuscatedAccountIdAndroid; final String? obfuscatedProfileIdAndroid; final String? packageNameAndroid; - final Platform platform; + final IapPlatform platform; final String productId; final PurchaseState purchaseState; final String? purchaseToken; final int quantity; final String? signatureAndroid; final double transactionDate; + + factory PurchaseAndroid.fromJson(Map json) { + return PurchaseAndroid( + autoRenewingAndroid: json['autoRenewingAndroid'] as bool?, + dataAndroid: json['dataAndroid'] as String?, + developerPayloadAndroid: json['developerPayloadAndroid'] as String?, + id: json['id'] as String, + ids: (json['ids'] as List?) == null ? null : (json['ids'] as List?)!.map((e) => e as String).toList(), + isAcknowledgedAndroid: json['isAcknowledgedAndroid'] as bool?, + isAutoRenewing: json['isAutoRenewing'] as bool, + obfuscatedAccountIdAndroid: json['obfuscatedAccountIdAndroid'] as String?, + obfuscatedProfileIdAndroid: json['obfuscatedProfileIdAndroid'] as String?, + packageNameAndroid: json['packageNameAndroid'] as String?, + platform: IapPlatform.fromJson(json['platform'] as String), + productId: json['productId'] as String, + purchaseState: PurchaseState.fromJson(json['purchaseState'] as String), + purchaseToken: json['purchaseToken'] as String?, + quantity: json['quantity'] as int, + signatureAndroid: json['signatureAndroid'] as String?, + transactionDate: (json['transactionDate'] as num).toDouble(), + ); + } + + @override + Map toJson() { + return { + '__typename': 'PurchaseAndroid', + 'autoRenewingAndroid': autoRenewingAndroid, + 'dataAndroid': dataAndroid, + 'developerPayloadAndroid': developerPayloadAndroid, + 'id': id, + 'ids': ids == null ? null : ids!.map((e) => e).toList(), + 'isAcknowledgedAndroid': isAcknowledgedAndroid, + 'isAutoRenewing': isAutoRenewing, + 'obfuscatedAccountIdAndroid': obfuscatedAccountIdAndroid, + 'obfuscatedProfileIdAndroid': obfuscatedProfileIdAndroid, + 'packageNameAndroid': packageNameAndroid, + 'platform': platform.toJson(), + 'productId': productId, + 'purchaseState': purchaseState.toJson(), + 'purchaseToken': purchaseToken, + 'quantity': quantity, + 'signatureAndroid': signatureAndroid, + 'transactionDate': transactionDate, + }; + } } class PurchaseError { @@ -548,9 +1330,26 @@ class PurchaseError { final ErrorCode code; final String message; final String? productId; + + factory PurchaseError.fromJson(Map json) { + return PurchaseError( + code: ErrorCode.fromJson(json['code'] as String), + message: json['message'] as String, + productId: json['productId'] as String?, + ); + } + + Map toJson() { + return { + '__typename': 'PurchaseError', + 'code': code.toJson(), + 'message': message, + 'productId': productId, + }; + } } -class PurchaseIOS implements PurchaseCommon, Purchase { +class PurchaseIOS extends Purchase implements PurchaseCommon { const PurchaseIOS({ this.appAccountToken, this.appBundleIdIOS, @@ -599,7 +1398,7 @@ class PurchaseIOS implements PurchaseCommon, Purchase { final double? originalTransactionDateIOS; final String? originalTransactionIdentifierIOS; final String? ownershipTypeIOS; - final Platform platform; + final IapPlatform platform; final String productId; final PurchaseState purchaseState; final String? purchaseToken; @@ -614,6 +1413,78 @@ class PurchaseIOS implements PurchaseCommon, Purchase { final double transactionDate; final String? transactionReasonIOS; final String? webOrderLineItemIdIOS; + + factory PurchaseIOS.fromJson(Map json) { + return PurchaseIOS( + appAccountToken: json['appAccountToken'] as String?, + appBundleIdIOS: json['appBundleIdIOS'] as String?, + countryCodeIOS: json['countryCodeIOS'] as String?, + currencyCodeIOS: json['currencyCodeIOS'] as String?, + currencySymbolIOS: json['currencySymbolIOS'] as String?, + environmentIOS: json['environmentIOS'] as String?, + expirationDateIOS: (json['expirationDateIOS'] as num?)?.toDouble(), + id: json['id'] as String, + ids: (json['ids'] as List?) == null ? null : (json['ids'] as List?)!.map((e) => e as String).toList(), + isAutoRenewing: json['isAutoRenewing'] as bool, + isUpgradedIOS: json['isUpgradedIOS'] as bool?, + offerIOS: json['offerIOS'] != null ? PurchaseOfferIOS.fromJson(json['offerIOS'] as Map) : null, + originalTransactionDateIOS: (json['originalTransactionDateIOS'] as num?)?.toDouble(), + originalTransactionIdentifierIOS: json['originalTransactionIdentifierIOS'] as String?, + ownershipTypeIOS: json['ownershipTypeIOS'] as String?, + platform: IapPlatform.fromJson(json['platform'] as String), + productId: json['productId'] as String, + purchaseState: PurchaseState.fromJson(json['purchaseState'] as String), + purchaseToken: json['purchaseToken'] as String?, + quantity: json['quantity'] as int, + quantityIOS: json['quantityIOS'] as int?, + reasonIOS: json['reasonIOS'] as String?, + reasonStringRepresentationIOS: json['reasonStringRepresentationIOS'] as String?, + revocationDateIOS: (json['revocationDateIOS'] as num?)?.toDouble(), + revocationReasonIOS: json['revocationReasonIOS'] as String?, + storefrontCountryCodeIOS: json['storefrontCountryCodeIOS'] as String?, + subscriptionGroupIdIOS: json['subscriptionGroupIdIOS'] as String?, + transactionDate: (json['transactionDate'] as num).toDouble(), + transactionReasonIOS: json['transactionReasonIOS'] as String?, + webOrderLineItemIdIOS: json['webOrderLineItemIdIOS'] as String?, + ); + } + + @override + Map toJson() { + return { + '__typename': 'PurchaseIOS', + 'appAccountToken': appAccountToken, + 'appBundleIdIOS': appBundleIdIOS, + 'countryCodeIOS': countryCodeIOS, + 'currencyCodeIOS': currencyCodeIOS, + 'currencySymbolIOS': currencySymbolIOS, + 'environmentIOS': environmentIOS, + 'expirationDateIOS': expirationDateIOS, + 'id': id, + 'ids': ids == null ? null : ids!.map((e) => e).toList(), + 'isAutoRenewing': isAutoRenewing, + 'isUpgradedIOS': isUpgradedIOS, + 'offerIOS': offerIOS?.toJson(), + 'originalTransactionDateIOS': originalTransactionDateIOS, + 'originalTransactionIdentifierIOS': originalTransactionIdentifierIOS, + 'ownershipTypeIOS': ownershipTypeIOS, + 'platform': platform.toJson(), + 'productId': productId, + 'purchaseState': purchaseState.toJson(), + 'purchaseToken': purchaseToken, + 'quantity': quantity, + 'quantityIOS': quantityIOS, + 'reasonIOS': reasonIOS, + 'reasonStringRepresentationIOS': reasonStringRepresentationIOS, + 'revocationDateIOS': revocationDateIOS, + 'revocationReasonIOS': revocationReasonIOS, + 'storefrontCountryCodeIOS': storefrontCountryCodeIOS, + 'subscriptionGroupIdIOS': subscriptionGroupIdIOS, + 'transactionDate': transactionDate, + 'transactionReasonIOS': transactionReasonIOS, + 'webOrderLineItemIdIOS': webOrderLineItemIdIOS, + }; + } } class PurchaseOfferIOS { @@ -626,9 +1497,26 @@ class PurchaseOfferIOS { final String id; final String paymentMode; final String type; + + factory PurchaseOfferIOS.fromJson(Map json) { + return PurchaseOfferIOS( + id: json['id'] as String, + paymentMode: json['paymentMode'] as String, + type: json['type'] as String, + ); + } + + Map toJson() { + return { + '__typename': 'PurchaseOfferIOS', + 'id': id, + 'paymentMode': paymentMode, + 'type': type, + }; + } } -class ReceiptValidationResultAndroid implements ReceiptValidationResult { +class ReceiptValidationResultAndroid extends ReceiptValidationResult { const ReceiptValidationResultAndroid({ required this.autoRenewing, required this.betaProduct, @@ -655,7 +1543,7 @@ class ReceiptValidationResultAndroid implements ReceiptValidationResult { final double? cancelDate; final String? cancelReason; final double? deferredDate; - final double? deferredSku; + final String? deferredSku; final double freeTrialEndDate; final double gracePeriodEndDate; final String parentProductId; @@ -668,9 +1556,57 @@ class ReceiptValidationResultAndroid implements ReceiptValidationResult { final String term; final String termSku; final bool testTransaction; + + factory ReceiptValidationResultAndroid.fromJson(Map json) { + return ReceiptValidationResultAndroid( + autoRenewing: json['autoRenewing'] as bool, + betaProduct: json['betaProduct'] as bool, + cancelDate: (json['cancelDate'] as num?)?.toDouble(), + cancelReason: json['cancelReason'] as String?, + deferredDate: (json['deferredDate'] as num?)?.toDouble(), + deferredSku: json['deferredSku'] as String?, + freeTrialEndDate: (json['freeTrialEndDate'] as num).toDouble(), + gracePeriodEndDate: (json['gracePeriodEndDate'] as num).toDouble(), + parentProductId: json['parentProductId'] as String, + productId: json['productId'] as String, + productType: json['productType'] as String, + purchaseDate: (json['purchaseDate'] as num).toDouble(), + quantity: json['quantity'] as int, + receiptId: json['receiptId'] as String, + renewalDate: (json['renewalDate'] as num).toDouble(), + term: json['term'] as String, + termSku: json['termSku'] as String, + testTransaction: json['testTransaction'] as bool, + ); + } + + @override + Map toJson() { + return { + '__typename': 'ReceiptValidationResultAndroid', + 'autoRenewing': autoRenewing, + 'betaProduct': betaProduct, + 'cancelDate': cancelDate, + 'cancelReason': cancelReason, + 'deferredDate': deferredDate, + 'deferredSku': deferredSku, + 'freeTrialEndDate': freeTrialEndDate, + 'gracePeriodEndDate': gracePeriodEndDate, + 'parentProductId': parentProductId, + 'productId': productId, + 'productType': productType, + 'purchaseDate': purchaseDate, + 'quantity': quantity, + 'receiptId': receiptId, + 'renewalDate': renewalDate, + 'term': term, + 'termSku': termSku, + 'testTransaction': testTransaction, + }; + } } -class ReceiptValidationResultIOS implements ReceiptValidationResult { +class ReceiptValidationResultIOS extends ReceiptValidationResult { const ReceiptValidationResultIOS({ /// Whether the receipt is valid required this.isValid, @@ -690,6 +1626,26 @@ class ReceiptValidationResultIOS implements ReceiptValidationResult { final Purchase? latestTransaction; /// Receipt data string final String receiptData; + + factory ReceiptValidationResultIOS.fromJson(Map json) { + return ReceiptValidationResultIOS( + isValid: json['isValid'] as bool, + jwsRepresentation: json['jwsRepresentation'] as String, + latestTransaction: json['latestTransaction'] != null ? Purchase.fromJson(json['latestTransaction'] as Map) : null, + receiptData: json['receiptData'] as String, + ); + } + + @override + Map toJson() { + return { + '__typename': 'ReceiptValidationResultIOS', + 'isValid': isValid, + 'jwsRepresentation': jwsRepresentation, + 'latestTransaction': latestTransaction?.toJson(), + 'receiptData': receiptData, + }; + } } class RefundResultIOS { @@ -700,6 +1656,21 @@ class RefundResultIOS { final String? message; final String status; + + factory RefundResultIOS.fromJson(Map json) { + return RefundResultIOS( + message: json['message'] as String?, + status: json['status'] as String, + ); + } + + Map toJson() { + return { + '__typename': 'RefundResultIOS', + 'message': message, + 'status': status, + }; + } } class RenewalInfoIOS { @@ -712,6 +1683,23 @@ class RenewalInfoIOS { final String? autoRenewPreference; final String? jsonRepresentation; final bool willAutoRenew; + + factory RenewalInfoIOS.fromJson(Map json) { + return RenewalInfoIOS( + autoRenewPreference: json['autoRenewPreference'] as String?, + jsonRepresentation: json['jsonRepresentation'] as String?, + willAutoRenew: json['willAutoRenew'] as bool, + ); + } + + Map toJson() { + return { + '__typename': 'RenewalInfoIOS', + 'autoRenewPreference': autoRenewPreference, + 'jsonRepresentation': jsonRepresentation, + 'willAutoRenew': willAutoRenew, + }; + } } class RequestPurchaseResult { @@ -722,6 +1710,21 @@ class RequestPurchaseResult { final Purchase? purchase; final List? purchases; + + factory RequestPurchaseResult.fromJson(Map json) { + return RequestPurchaseResult( + purchase: json['purchase'] != null ? Purchase.fromJson(json['purchase'] as Map) : null, + purchases: (json['purchases'] as List?) == null ? null : (json['purchases'] as List?)!.map((e) => Purchase.fromJson(e as Map)).toList(), + ); + } + + Map toJson() { + return { + '__typename': 'RequestPurchaseResult', + 'purchase': purchase?.toJson(), + 'purchases': purchases == null ? null : purchases!.map((e) => e.toJson()).toList(), + }; + } } class SubscriptionInfoIOS { @@ -736,6 +1739,25 @@ class SubscriptionInfoIOS { final List? promotionalOffers; final String subscriptionGroupId; final SubscriptionPeriodValueIOS subscriptionPeriod; + + factory SubscriptionInfoIOS.fromJson(Map json) { + return SubscriptionInfoIOS( + introductoryOffer: json['introductoryOffer'] != null ? SubscriptionOfferIOS.fromJson(json['introductoryOffer'] as Map) : null, + promotionalOffers: (json['promotionalOffers'] as List?) == null ? null : (json['promotionalOffers'] as List?)!.map((e) => SubscriptionOfferIOS.fromJson(e as Map)).toList(), + subscriptionGroupId: json['subscriptionGroupId'] as String, + subscriptionPeriod: SubscriptionPeriodValueIOS.fromJson(json['subscriptionPeriod'] as Map), + ); + } + + Map toJson() { + return { + '__typename': 'SubscriptionInfoIOS', + 'introductoryOffer': introductoryOffer?.toJson(), + 'promotionalOffers': promotionalOffers == null ? null : promotionalOffers!.map((e) => e.toJson()).toList(), + 'subscriptionGroupId': subscriptionGroupId, + 'subscriptionPeriod': subscriptionPeriod.toJson(), + }; + } } class SubscriptionOfferIOS { @@ -756,6 +1778,31 @@ class SubscriptionOfferIOS { final int periodCount; final double price; final SubscriptionOfferTypeIOS type; + + factory SubscriptionOfferIOS.fromJson(Map json) { + return SubscriptionOfferIOS( + displayPrice: json['displayPrice'] as String, + id: json['id'] as String, + paymentMode: PaymentModeIOS.fromJson(json['paymentMode'] as String), + period: SubscriptionPeriodValueIOS.fromJson(json['period'] as Map), + periodCount: json['periodCount'] as int, + price: (json['price'] as num).toDouble(), + type: SubscriptionOfferTypeIOS.fromJson(json['type'] as String), + ); + } + + Map toJson() { + return { + '__typename': 'SubscriptionOfferIOS', + 'displayPrice': displayPrice, + 'id': id, + 'paymentMode': paymentMode.toJson(), + 'period': period.toJson(), + 'periodCount': periodCount, + 'price': price, + 'type': type.toJson(), + }; + } } class SubscriptionPeriodValueIOS { @@ -766,6 +1813,21 @@ class SubscriptionPeriodValueIOS { final SubscriptionPeriodIOS unit; final int value; + + factory SubscriptionPeriodValueIOS.fromJson(Map json) { + return SubscriptionPeriodValueIOS( + unit: SubscriptionPeriodIOS.fromJson(json['unit'] as String), + value: json['value'] as int, + ); + } + + Map toJson() { + return { + '__typename': 'SubscriptionPeriodValueIOS', + 'unit': unit.toJson(), + 'value': value, + }; + } } class SubscriptionStatusIOS { @@ -776,6 +1838,21 @@ class SubscriptionStatusIOS { final RenewalInfoIOS? renewalInfo; final String state; + + factory SubscriptionStatusIOS.fromJson(Map json) { + return SubscriptionStatusIOS( + renewalInfo: json['renewalInfo'] != null ? RenewalInfoIOS.fromJson(json['renewalInfo'] as Map) : null, + state: json['state'] as String, + ); + } + + Map toJson() { + return { + '__typename': 'SubscriptionStatusIOS', + 'renewalInfo': renewalInfo?.toJson(), + 'state': state, + }; + } } class VoidResult { @@ -784,6 +1861,19 @@ class VoidResult { }); final bool success; + + factory VoidResult.fromJson(Map json) { + return VoidResult( + success: json['success'] as bool, + ); + } + + Map toJson() { + return { + '__typename': 'VoidResult', + 'success': success, + }; + } } // MARK: - Input Objects @@ -800,6 +1890,20 @@ class AndroidSubscriptionOfferInput { final String offerToken; /// Product SKU final String sku; + + factory AndroidSubscriptionOfferInput.fromJson(Map json) { + return AndroidSubscriptionOfferInput( + offerToken: json['offerToken'] as String, + sku: json['sku'] as String, + ); + } + + Map toJson() { + return { + 'offerToken': offerToken, + 'sku': sku, + }; + } } class DeepLinkOptions { @@ -814,6 +1918,20 @@ class DeepLinkOptions { final String? packageNameAndroid; /// Android SKU to open (required on Android) final String? skuAndroid; + + factory DeepLinkOptions.fromJson(Map json) { + return DeepLinkOptions( + packageNameAndroid: json['packageNameAndroid'] as String?, + skuAndroid: json['skuAndroid'] as String?, + ); + } + + Map toJson() { + return { + 'packageNameAndroid': packageNameAndroid, + 'skuAndroid': skuAndroid, + }; + } } class DiscountOfferInputIOS { @@ -840,6 +1958,26 @@ class DiscountOfferInputIOS { final String signature; /// Timestamp of discount offer final double timestamp; + + factory DiscountOfferInputIOS.fromJson(Map json) { + return DiscountOfferInputIOS( + identifier: json['identifier'] as String, + keyIdentifier: json['keyIdentifier'] as String, + nonce: json['nonce'] as String, + signature: json['signature'] as String, + timestamp: (json['timestamp'] as num).toDouble(), + ); + } + + Map toJson() { + return { + 'identifier': identifier, + 'keyIdentifier': keyIdentifier, + 'nonce': nonce, + 'signature': signature, + 'timestamp': timestamp, + }; + } } class ProductRequest { @@ -850,6 +1988,20 @@ class ProductRequest { final List skus; final ProductQueryType? type; + + factory ProductRequest.fromJson(Map json) { + return ProductRequest( + skus: (json['skus'] as List).map((e) => e as String).toList(), + type: json['type'] != null ? ProductQueryType.fromJson(json['type'] as String) : null, + ); + } + + Map toJson() { + return { + 'skus': skus.map((e) => e).toList(), + 'type': type?.toJson(), + }; + } } class PurchaseInput { @@ -868,12 +2020,40 @@ class PurchaseInput { final String id; final List? ids; final bool isAutoRenewing; - final Platform platform; + final IapPlatform platform; final String productId; final PurchaseState purchaseState; final String? purchaseToken; final int quantity; final double transactionDate; + + factory PurchaseInput.fromJson(Map json) { + return PurchaseInput( + id: json['id'] as String, + ids: (json['ids'] as List?) == null ? null : (json['ids'] as List?)!.map((e) => e as String).toList(), + isAutoRenewing: json['isAutoRenewing'] as bool, + platform: IapPlatform.fromJson(json['platform'] as String), + productId: json['productId'] as String, + purchaseState: PurchaseState.fromJson(json['purchaseState'] as String), + purchaseToken: json['purchaseToken'] as String?, + quantity: json['quantity'] as int, + transactionDate: (json['transactionDate'] as num).toDouble(), + ); + } + + Map toJson() { + return { + 'id': id, + 'ids': ids == null ? null : ids!.map((e) => e).toList(), + 'isAutoRenewing': isAutoRenewing, + 'platform': platform.toJson(), + 'productId': productId, + 'purchaseState': purchaseState.toJson(), + 'purchaseToken': purchaseToken, + 'quantity': quantity, + 'transactionDate': transactionDate, + }; + } } class PurchaseOptions { @@ -888,6 +2068,20 @@ class PurchaseOptions { final bool? alsoPublishToEventListenerIOS; /// Limit to currently active items on iOS final bool? onlyIncludeActiveItemsIOS; + + factory PurchaseOptions.fromJson(Map json) { + return PurchaseOptions( + alsoPublishToEventListenerIOS: json['alsoPublishToEventListenerIOS'] as bool?, + onlyIncludeActiveItemsIOS: json['onlyIncludeActiveItemsIOS'] as bool?, + ); + } + + Map toJson() { + return { + 'alsoPublishToEventListenerIOS': alsoPublishToEventListenerIOS, + 'onlyIncludeActiveItemsIOS': onlyIncludeActiveItemsIOS, + }; + } } class PurchaseParams { @@ -906,6 +2100,22 @@ class PurchaseParams { final RequestSubscriptionPropsByPlatforms? requestSubscription; /// Explicit purchase type hint (defaults to in-app) final ProductQueryType? type; + + factory PurchaseParams.fromJson(Map json) { + return PurchaseParams( + requestPurchase: json['requestPurchase'] != null ? RequestPurchasePropsByPlatforms.fromJson(json['requestPurchase'] as Map) : null, + requestSubscription: json['requestSubscription'] != null ? RequestSubscriptionPropsByPlatforms.fromJson(json['requestSubscription'] as Map) : null, + type: json['type'] != null ? ProductQueryType.fromJson(json['type'] as String) : null, + ); + } + + Map toJson() { + return { + 'requestPurchase': requestPurchase?.toJson(), + 'requestSubscription': requestSubscription?.toJson(), + 'type': type?.toJson(), + }; + } } class ReceiptValidationAndroidOptions { @@ -920,6 +2130,24 @@ class ReceiptValidationAndroidOptions { final bool? isSub; final String packageName; final String productToken; + + factory ReceiptValidationAndroidOptions.fromJson(Map json) { + return ReceiptValidationAndroidOptions( + accessToken: json['accessToken'] as String, + isSub: json['isSub'] as bool?, + packageName: json['packageName'] as String, + productToken: json['productToken'] as String, + ); + } + + Map toJson() { + return { + 'accessToken': accessToken, + 'isSub': isSub, + 'packageName': packageName, + 'productToken': productToken, + }; + } } class ReceiptValidationProps { @@ -934,6 +2162,20 @@ class ReceiptValidationProps { final ReceiptValidationAndroidOptions? androidOptions; /// Product SKU to validate final String sku; + + factory ReceiptValidationProps.fromJson(Map json) { + return ReceiptValidationProps( + androidOptions: json['androidOptions'] != null ? ReceiptValidationAndroidOptions.fromJson(json['androidOptions'] as Map) : null, + sku: json['sku'] as String, + ); + } + + Map toJson() { + return { + 'androidOptions': androidOptions?.toJson(), + 'sku': sku, + }; + } } class RequestPurchaseAndroidProps { @@ -956,6 +2198,24 @@ class RequestPurchaseAndroidProps { final String? obfuscatedProfileIdAndroid; /// List of product SKUs final List skus; + + factory RequestPurchaseAndroidProps.fromJson(Map json) { + return RequestPurchaseAndroidProps( + isOfferPersonalized: json['isOfferPersonalized'] as bool?, + obfuscatedAccountIdAndroid: json['obfuscatedAccountIdAndroid'] as String?, + obfuscatedProfileIdAndroid: json['obfuscatedProfileIdAndroid'] as String?, + skus: (json['skus'] as List).map((e) => e as String).toList(), + ); + } + + Map toJson() { + return { + 'isOfferPersonalized': isOfferPersonalized, + 'obfuscatedAccountIdAndroid': obfuscatedAccountIdAndroid, + 'obfuscatedProfileIdAndroid': obfuscatedProfileIdAndroid, + 'skus': skus.map((e) => e).toList(), + }; + } } class RequestPurchaseIosProps { @@ -982,6 +2242,26 @@ class RequestPurchaseIosProps { final String sku; /// Discount offer to apply final DiscountOfferInputIOS? withOffer; + + factory RequestPurchaseIosProps.fromJson(Map json) { + return RequestPurchaseIosProps( + andDangerouslyFinishTransactionAutomatically: json['andDangerouslyFinishTransactionAutomatically'] as bool?, + appAccountToken: json['appAccountToken'] as String?, + quantity: json['quantity'] as int?, + sku: json['sku'] as String, + withOffer: json['withOffer'] != null ? DiscountOfferInputIOS.fromJson(json['withOffer'] as Map) : null, + ); + } + + Map toJson() { + return { + 'andDangerouslyFinishTransactionAutomatically': andDangerouslyFinishTransactionAutomatically, + 'appAccountToken': appAccountToken, + 'quantity': quantity, + 'sku': sku, + 'withOffer': withOffer?.toJson(), + }; + } } class RequestPurchaseProps { @@ -996,6 +2276,20 @@ class RequestPurchaseProps { final RequestPurchaseAndroidProps? android; /// iOS-specific purchase parameters final RequestPurchaseIosProps? ios; + + factory RequestPurchaseProps.fromJson(Map json) { + return RequestPurchaseProps( + android: json['android'] != null ? RequestPurchaseAndroidProps.fromJson(json['android'] as Map) : null, + ios: json['ios'] != null ? RequestPurchaseIosProps.fromJson(json['ios'] as Map) : null, + ); + } + + Map toJson() { + return { + 'android': android?.toJson(), + 'ios': ios?.toJson(), + }; + } } class RequestPurchasePropsByPlatforms { @@ -1010,6 +2304,20 @@ class RequestPurchasePropsByPlatforms { final RequestPurchaseAndroidProps? android; /// iOS-specific purchase parameters final RequestPurchaseIosProps? ios; + + factory RequestPurchasePropsByPlatforms.fromJson(Map json) { + return RequestPurchasePropsByPlatforms( + android: json['android'] != null ? RequestPurchaseAndroidProps.fromJson(json['android'] as Map) : null, + ios: json['ios'] != null ? RequestPurchaseIosProps.fromJson(json['ios'] as Map) : null, + ); + } + + Map toJson() { + return { + 'android': android?.toJson(), + 'ios': ios?.toJson(), + }; + } } class RequestSubscriptionAndroidProps { @@ -1044,6 +2352,30 @@ class RequestSubscriptionAndroidProps { final List skus; /// Subscription offers final List? subscriptionOffers; + + factory RequestSubscriptionAndroidProps.fromJson(Map json) { + return RequestSubscriptionAndroidProps( + isOfferPersonalized: json['isOfferPersonalized'] as bool?, + obfuscatedAccountIdAndroid: json['obfuscatedAccountIdAndroid'] as String?, + obfuscatedProfileIdAndroid: json['obfuscatedProfileIdAndroid'] as String?, + purchaseTokenAndroid: json['purchaseTokenAndroid'] as String?, + replacementModeAndroid: json['replacementModeAndroid'] as int?, + skus: (json['skus'] as List).map((e) => e as String).toList(), + subscriptionOffers: (json['subscriptionOffers'] as List?) == null ? null : (json['subscriptionOffers'] as List?)!.map((e) => AndroidSubscriptionOfferInput.fromJson(e as Map)).toList(), + ); + } + + Map toJson() { + return { + 'isOfferPersonalized': isOfferPersonalized, + 'obfuscatedAccountIdAndroid': obfuscatedAccountIdAndroid, + 'obfuscatedProfileIdAndroid': obfuscatedProfileIdAndroid, + 'purchaseTokenAndroid': purchaseTokenAndroid, + 'replacementModeAndroid': replacementModeAndroid, + 'skus': skus.map((e) => e).toList(), + 'subscriptionOffers': subscriptionOffers == null ? null : subscriptionOffers!.map((e) => e.toJson()).toList(), + }; + } } class RequestSubscriptionIosProps { @@ -1060,6 +2392,26 @@ class RequestSubscriptionIosProps { final int? quantity; final String sku; final DiscountOfferInputIOS? withOffer; + + factory RequestSubscriptionIosProps.fromJson(Map json) { + return RequestSubscriptionIosProps( + andDangerouslyFinishTransactionAutomatically: json['andDangerouslyFinishTransactionAutomatically'] as bool?, + appAccountToken: json['appAccountToken'] as String?, + quantity: json['quantity'] as int?, + sku: json['sku'] as String, + withOffer: json['withOffer'] != null ? DiscountOfferInputIOS.fromJson(json['withOffer'] as Map) : null, + ); + } + + Map toJson() { + return { + 'andDangerouslyFinishTransactionAutomatically': andDangerouslyFinishTransactionAutomatically, + 'appAccountToken': appAccountToken, + 'quantity': quantity, + 'sku': sku, + 'withOffer': withOffer?.toJson(), + }; + } } class RequestSubscriptionPropsByPlatforms { @@ -1073,18 +2425,92 @@ class RequestSubscriptionPropsByPlatforms { /// Android-specific subscription parameters final RequestSubscriptionAndroidProps? android; /// iOS-specific subscription parameters - final RequestPurchaseIosProps? ios; + final RequestSubscriptionIosProps? ios; + + factory RequestSubscriptionPropsByPlatforms.fromJson(Map json) { + return RequestSubscriptionPropsByPlatforms( + android: json['android'] != null ? RequestSubscriptionAndroidProps.fromJson(json['android'] as Map) : null, + ios: json['ios'] != null ? RequestSubscriptionIosProps.fromJson(json['ios'] as Map) : null, + ); + } + + Map toJson() { + return { + 'android': android?.toJson(), + 'ios': ios?.toJson(), + }; + } } // MARK: - Unions -abstract class Product {} +sealed class Product { + const Product(); + + factory Product.fromJson(Map json) { + final typeName = json['__typename'] as String?; + switch (typeName) { + case 'ProductAndroid': + return ProductAndroid.fromJson(json); + case 'ProductIOS': + return ProductIOS.fromJson(json); + } + throw ArgumentError('Unknown __typename for Product: $typeName'); + } + + Map toJson(); +} -abstract class ProductSubscription {} +sealed class ProductSubscription { + const ProductSubscription(); + + factory ProductSubscription.fromJson(Map json) { + final typeName = json['__typename'] as String?; + switch (typeName) { + case 'ProductSubscriptionAndroid': + return ProductSubscriptionAndroid.fromJson(json); + case 'ProductSubscriptionIOS': + return ProductSubscriptionIOS.fromJson(json); + } + throw ArgumentError('Unknown __typename for ProductSubscription: $typeName'); + } + + Map toJson(); +} -abstract class Purchase {} +sealed class Purchase { + const Purchase(); + + factory Purchase.fromJson(Map json) { + final typeName = json['__typename'] as String?; + switch (typeName) { + case 'PurchaseAndroid': + return PurchaseAndroid.fromJson(json); + case 'PurchaseIOS': + return PurchaseIOS.fromJson(json); + } + throw ArgumentError('Unknown __typename for Purchase: $typeName'); + } + + Map toJson(); +} -abstract class ReceiptValidationResult {} +sealed class ReceiptValidationResult { + const ReceiptValidationResult(); + + factory ReceiptValidationResult.fromJson(Map json) { + final typeName = json['__typename'] as String?; + switch (typeName) { + case 'ReceiptValidationResultAndroid': + return ReceiptValidationResultAndroid.fromJson(json); + case 'ReceiptValidationResultIOS': + return ReceiptValidationResultIOS.fromJson(json); + } + throw ArgumentError('Unknown __typename for ReceiptValidationResult: $typeName'); + } + + Map toJson(); +} // MARK: - Root Operations diff --git a/src/generated/types.ts b/src/generated/types.ts index 784be1a..56130f2 100644 --- a/src/generated/types.ts +++ b/src/generated/types.ts @@ -131,11 +131,9 @@ export interface FetchProductsResult { subscriptions?: (ProductSubscription[] | null); } -export enum IapEvent { - PromotedProductIos = 'PROMOTED_PRODUCT_IOS', - PurchaseError = 'PURCHASE_ERROR', - PurchaseUpdated = 'PURCHASE_UPDATED' -} +export type IapEvent = 'promoted-product-ios' | 'purchase-error' | 'purchase-updated'; + +export type IapPlatform = 'android' | 'ios'; export interface Mutation { /** Acknowledge a non-consumable purchase or subscription */ @@ -206,17 +204,7 @@ export interface MutationValidateReceiptArgs { options: ReceiptValidationProps; } -export enum PaymentModeIOS { - Empty = 'EMPTY', - FreeTrial = 'FREE_TRIAL', - PayAsYouGo = 'PAY_AS_YOU_GO', - PayUpFront = 'PAY_UP_FRONT' -} - -export enum Platform { - Android = 'ANDROID', - Ios = 'IOS' -} +export type PaymentModeIOS = 'empty' | 'free-trial' | 'pay-as-you-go' | 'pay-up-front'; export interface PricingPhaseAndroid { billingCycleCount: number; @@ -242,7 +230,7 @@ export interface ProductAndroid extends ProductCommon { id: string; nameAndroid: string; oneTimePurchaseOfferDetailsAndroid?: (ProductAndroidOneTimePurchaseOfferDetail | null); - platform: Platform; + platform: IapPlatform; price?: (number | null); subscriptionOfferDetailsAndroid?: (ProductSubscriptionAndroidOfferDetails[] | null); title: string; @@ -262,7 +250,7 @@ export interface ProductCommon { displayName?: (string | null); displayPrice: string; id: string; - platform: Platform; + platform: IapPlatform; price?: (number | null); title: string; type: ProductType; @@ -278,7 +266,7 @@ export interface ProductIOS extends ProductCommon { id: string; isFamilyShareableIOS: boolean; jsonRepresentationIOS: string; - platform: Platform; + platform: IapPlatform; price?: (number | null); subscriptionInfoIOS?: (SubscriptionInfoIOS | null); title: string; @@ -286,11 +274,7 @@ export interface ProductIOS extends ProductCommon { typeIOS: ProductTypeIOS; } -export enum ProductQueryType { - All = 'ALL', - InApp = 'IN_APP', - Subs = 'SUBS' -} +export type ProductQueryType = 'all' | 'in-app' | 'subs'; export interface ProductRequest { skus: string[]; @@ -308,7 +292,7 @@ export interface ProductSubscriptionAndroid extends ProductCommon { id: string; nameAndroid: string; oneTimePurchaseOfferDetailsAndroid?: (ProductAndroidOneTimePurchaseOfferDetail | null); - platform: Platform; + platform: IapPlatform; price?: (number | null); subscriptionOfferDetailsAndroid: ProductSubscriptionAndroidOfferDetails[]; title: string; @@ -339,7 +323,7 @@ export interface ProductSubscriptionIOS extends ProductCommon { introductoryPriceSubscriptionPeriodIOS?: (SubscriptionPeriodIOS | null); isFamilyShareableIOS: boolean; jsonRepresentationIOS: string; - platform: Platform; + platform: IapPlatform; price?: (number | null); subscriptionInfoIOS?: (SubscriptionInfoIOS | null); subscriptionPeriodNumberIOS?: (string | null); @@ -349,17 +333,9 @@ export interface ProductSubscriptionIOS extends ProductCommon { typeIOS: ProductTypeIOS; } -export enum ProductType { - InApp = 'IN_APP', - Subs = 'SUBS' -} +export type ProductType = 'in-app' | 'subs'; -export enum ProductTypeIOS { - AutoRenewableSubscription = 'AUTO_RENEWABLE_SUBSCRIPTION', - Consumable = 'CONSUMABLE', - NonConsumable = 'NON_CONSUMABLE', - NonRenewingSubscription = 'NON_RENEWING_SUBSCRIPTION' -} +export type ProductTypeIOS = 'auto-renewable-subscription' | 'consumable' | 'non-consumable' | 'non-renewing-subscription'; export type Purchase = PurchaseAndroid | PurchaseIOS; @@ -374,7 +350,7 @@ export interface PurchaseAndroid extends PurchaseCommon { obfuscatedAccountIdAndroid?: (string | null); obfuscatedProfileIdAndroid?: (string | null); packageNameAndroid?: (string | null); - platform: Platform; + platform: IapPlatform; productId: string; purchaseState: PurchaseState; purchaseToken?: (string | null); @@ -387,7 +363,7 @@ export interface PurchaseCommon { id: string; ids?: (string[] | null); isAutoRenewing: boolean; - platform: Platform; + platform: IapPlatform; productId: string; purchaseState: PurchaseState; /** Unified purchase token (iOS JWS, Android purchaseToken) */ @@ -418,7 +394,7 @@ export interface PurchaseIOS extends PurchaseCommon { originalTransactionDateIOS?: (number | null); originalTransactionIdentifierIOS?: (string | null); ownershipTypeIOS?: (string | null); - platform: Platform; + platform: IapPlatform; productId: string; purchaseState: PurchaseState; purchaseToken?: (string | null); @@ -439,7 +415,7 @@ export interface PurchaseInput { id: string; ids?: (string[] | null); isAutoRenewing: boolean; - platform: Platform; + platform: IapPlatform; productId: string; purchaseState: PurchaseState; purchaseToken?: (string | null); @@ -469,14 +445,7 @@ export interface PurchaseParams { type?: (ProductQueryType | null); } -export enum PurchaseState { - Deferred = 'DEFERRED', - Failed = 'FAILED', - Pending = 'PENDING', - Purchased = 'PURCHASED', - Restored = 'RESTORED', - Unknown = 'UNKNOWN' -} +export type PurchaseState = 'deferred' | 'failed' | 'pending' | 'purchased' | 'restored' | 'unknown'; export interface Query { /** Get current StoreKit 2 entitlements (iOS 15+) */ @@ -583,7 +552,7 @@ export interface ReceiptValidationResultAndroid { cancelDate?: (number | null); cancelReason?: (string | null); deferredDate?: (number | null); - deferredSku?: (number | null); + deferredSku?: (string | null); freeTrialEndDate: number; gracePeriodEndDate: number; parentProductId: string; @@ -692,7 +661,7 @@ export interface RequestSubscriptionPropsByPlatforms { /** Android-specific subscription parameters */ android?: (RequestSubscriptionAndroidProps | null); /** iOS-specific subscription parameters */ - ios?: (RequestPurchaseIosProps | null); + ios?: (RequestSubscriptionIosProps | null); } export interface Subscription { @@ -721,18 +690,9 @@ export interface SubscriptionOfferIOS { type: SubscriptionOfferTypeIOS; } -export enum SubscriptionOfferTypeIOS { - Introductory = 'INTRODUCTORY', - Promotional = 'PROMOTIONAL' -} +export type SubscriptionOfferTypeIOS = 'introductory' | 'promotional'; -export enum SubscriptionPeriodIOS { - Day = 'DAY', - Empty = 'EMPTY', - Month = 'MONTH', - Week = 'WEEK', - Year = 'YEAR' -} +export type SubscriptionPeriodIOS = 'day' | 'empty' | 'month' | 'week' | 'year'; export interface SubscriptionPeriodValueIOS { unit: SubscriptionPeriodIOS; diff --git a/src/type-android.graphql b/src/type-android.graphql index b05e671..1926235 100644 --- a/src/type-android.graphql +++ b/src/type-android.graphql @@ -39,7 +39,7 @@ type ProductAndroid implements ProductCommon { currency: String! price: Float debugDescription: String - platform: Platform! + platform: IapPlatform! # Android-specific nameAndroid: String! @@ -58,7 +58,7 @@ type ProductSubscriptionAndroid implements ProductCommon { currency: String! price: Float debugDescription: String - platform: Platform! + platform: IapPlatform! # Android-specific nameAndroid: String! @@ -73,7 +73,7 @@ type PurchaseAndroid implements PurchaseCommon { ids: [String!] transactionDate: Float! purchaseToken: String - platform: Platform! + platform: IapPlatform! quantity: Int! purchaseState: PurchaseState! isAutoRenewing: Boolean! @@ -164,7 +164,7 @@ type ReceiptValidationResultAndroid { cancelDate: Float cancelReason: String deferredDate: Float - deferredSku: Float + deferredSku: String freeTrialEndDate: Float! gracePeriodEndDate: Float! parentProductId: String! diff --git a/src/type-ios.graphql b/src/type-ios.graphql index acd3e32..0a9eccc 100644 --- a/src/type-ios.graphql +++ b/src/type-ios.graphql @@ -67,7 +67,7 @@ type ProductIOS implements ProductCommon { currency: String! price: Float debugDescription: String - platform: Platform! + platform: IapPlatform! # iOS-specific displayNameIOS: String! @@ -89,7 +89,7 @@ type ProductSubscriptionIOS implements ProductCommon { currency: String! price: Float debugDescription: String - platform: Platform! + platform: IapPlatform! # iOS-specific displayNameIOS: String! @@ -128,7 +128,7 @@ type PurchaseIOS implements PurchaseCommon { ids: [String!] transactionDate: Float! purchaseToken: String - platform: Platform! + platform: IapPlatform! quantity: Int! purchaseState: PurchaseState! isAutoRenewing: Boolean! diff --git a/src/type.graphql b/src/type.graphql index 4ce70a9..ddc1718 100644 --- a/src/type.graphql +++ b/src/type.graphql @@ -1,8 +1,8 @@ # openiap.dev GraphQL Types for cross-platform IAP (common) # Platform discriminators -enum Platform { - Ios +enum IapPlatform { + IOS Android } @@ -26,7 +26,7 @@ enum PurchaseState { enum IapEvent { PurchaseUpdated PurchaseError - PromotedProductIos + PromotedProductIOS } # Common product fields @@ -40,7 +40,7 @@ interface ProductCommon { currency: String! price: Float debugDescription: String - platform: Platform! + platform: IapPlatform! } # Common purchase fields @@ -53,7 +53,7 @@ interface PurchaseCommon { Unified purchase token (iOS JWS, Android purchaseToken) """ purchaseToken: String - platform: Platform! + platform: IapPlatform! quantity: Int! purchaseState: PurchaseState! isAutoRenewing: Boolean! @@ -128,7 +128,7 @@ input PurchaseInput { ids: [String!] transactionDate: Float! purchaseToken: String - platform: Platform! + platform: IapPlatform! quantity: Int! purchaseState: PurchaseState! isAutoRenewing: Boolean! @@ -173,7 +173,7 @@ input RequestSubscriptionPropsByPlatforms { """ iOS-specific subscription parameters """ - ios: RequestPurchaseIosProps + ios: RequestSubscriptionIosProps """ Android-specific subscription parameters """