Giter Site home page Giter Site logo

Comments (27)

szantogab avatar szantogab commented on July 23, 2024 10

@NiltiakSivad I dug a little deeper, and I found that Apollo CLI now expects the parameter this way: --passthroughCustomScalars.

You can check out Apollo CLI's other parameters here:
https://github.com/apollographql/apollo-cli#apollo-codegengenerate-output

Hope this helps you :)

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024 6

thanks @martijnwalraven! judging by the nature of centAmount field, I think the value can be pretty high in some cases
the current workaround could be manually altering the local schema file; is there anything better you’d suggest?

I hope to add better support for custom scalars soon, but in the meantime there is a temporary apollo-codegen option --passthrough-custom-scalars that doesn't attempt to map custom scalars to string but keeps them as is. That means you're responsible for defining the type and making sure it is JSONDecodable and JSONEncodable.

I haven't tested it, but something like this should work:

typealias Long = Int64

extension Int64: JSONDecodable, JSONEncodable {
  public init(jsonValue value: JSONValue) throws {
    guard let string = value as? String else {
      throw JSONDecodingError.couldNotConvert(value: value, to: String.self)
    }
    guard let number = Int64(string) else {
      throw JSONDecodingError.couldNotConvert(value: value, to: Int64.self)
    }

    self = number
  }

  public var jsonValue: JSONValue {
    return String(self)
  }
}

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024

According to the GraphQL spec, Long is not a built-in scalar, so it is treated as a custom scalar. Right now in Apollo iOS, all custom scalars are mapped to string (which is also how they are encoded in JSON).

I would definitely like to add better support for custom scalars, which should give you the opportunity to define your own mapping.

But in this case, do you really need Long here, or would Int suffice?

from apollo-ios.

AnandWalvekar avatar AnandWalvekar commented on July 23, 2024

Hi @martijnwalraven
I am getting an error on iOS client

Error
"Error at path "history.itemid": couldNotConvert(value: 1100025, to: Swift.String)"

System Info

  • apollo-codegen version : 0.16.5

  • Apollo Client SDK version : (0.6.2)

  • schema.json type
    { "defaultValue": null, "name": "itemId", "description": null, "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", "name": "Long", "ofType": null } } }

What I tried
Tried extension you have mentioned and updated the build generation script in Xcode -> Build Phases -> Ran Script
$APOLLO_FRAMEWORK_PATH/check-and-run-apollo-codegen.sh generate $(find . -name '*.graphql') --schema schema.json --output API.swift --passthrough-custom-scalars

Please let me know if I am going wrong somewhere

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024

@AnandWalvekar: Does the generated API code reference Long? Where are you including typealias Long = Int64 and the extension?

from apollo-ios.

AnandWalvekar avatar AnandWalvekar commented on July 23, 2024

@martijnwalraven
Yes it is having Long
public var itemId: Long
I have included both typealias & extension in a new file in my project as
import Apollo
public typealias Long = Int64

But still getting the same error

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024

@AnandWalvekar: That is surprising. Can you check if the generated API code includes a typealias Long = String by any chance? (It shouldn't, because you specify --passthrough-custom-scalars. But then even if it doesn't pick up your typealias Long, it should fail with a compiler error.)

from apollo-ios.

AnandWalvekar avatar AnandWalvekar commented on July 23, 2024

@martijnwalraven
It works if I write like below
guard let long = value as? Long else { throw JSONDecodingError.couldNotConvert(value: value, to: String.self) } self = long

Is this the solution?

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024

@AnandWalvekar: Ah, so you're encoding Long as a JSON number instead of a string! If that's the case, something like your code would work (although you may want to change the error message as well).

Note that numbers in JavaScript can't represent 64-bit integers however, so unless you're sure the value will never exceed Number.MAX_SAFE_INTEGER (2^53 - 1), that might lead to unexpected problems.

from apollo-ios.

AnandWalvekar avatar AnandWalvekar commented on July 23, 2024

@martijnwalraven
Understood. Thank you very much for your quick support.

from apollo-ios.

NiltiakSivad avatar NiltiakSivad commented on July 23, 2024

@martijnwalraven suggestion worked fine for me originally, but the latest Apollo code generation script installation changes does not accept the --passthrough-custom-scalars option. Worked with check-and-run-apollo-codegen.sh (Apollo 0.8) but does not work with the new check-and-run-apollo-cli.sh (Apollo 0.9.2).

from apollo-ios.

szantogab avatar szantogab commented on July 23, 2024

@NiltiakSivad same problem here.. :(

from apollo-ios.

NiltiakSivad avatar NiltiakSivad commented on July 23, 2024

@szantogab I re-read martijnwalraven's post and he does mention it's a "temporary" flag. I'm not sure if anything is mentioned about its removal and future plans in another issue/merge request, I need to investigate more, if I find anything I'll post here.

from apollo-ios.

daksharma avatar daksharma commented on July 23, 2024

Hi @martijnwalraven
It seems like the typealias was a viable solution for many people. I tried the typealias Long = Int64 and the extension that you have posted above.
When generating the API.swift file I am using the ----passthroughCustomScalars flag, when building the project Xcode/Swift complains about Property cannot be declared public because its type uses an internal type.

I am using Apollo through Cocoapods and the Apollo cli (not apollo-codegen) as well as the script provided in the installation process of the apollo ios website.
I tried both Swift 4 and Swift 4.2 in the build settings. but the error persists.

This error is in the API.swift file. No typealias is declared in the generated file.
screen shot 2018-10-16 at 1 20 16 pm

Since API.swift should not be modified, any idea on how this can be resolved.

EDIT: Solved :)

from apollo-ios.

jtoce avatar jtoce commented on July 23, 2024

Since API.swift should not be modified, any idea on how this can be resolved.

EDIT: Solved :)

I copy the code into Long.swift and then changed the line to read public typealias Long = Int64.

from apollo-ios.

john1452 avatar john1452 commented on July 23, 2024

Hi @martijnwalraven

Is there a workaround to use "Any" as custom type?
One of the API i am consuming returns "Object" type which can contain Int Decimal or a string value.

I tried the following but it will not work.

public typealias Object = Any
extension Object : JSONDecodable, JSONEncodable { }

Any help is appreciated

Thanks!

from apollo-ios.

daoseng33 avatar daoseng33 commented on July 23, 2024

Remember to import Apollo and conform "JSONDecodable", not inherit "JSONDecoder"...
(I'm stuck for this for an hour... such a fool)

from apollo-ios.

niraj1991 avatar niraj1991 commented on July 23, 2024

Hi @martijnwalraven

I am getting an error on iOS client. Incorrect code generation: String instead of Array.

The resulting API.swift that was generated using apollo-ios

GraphQLField("reactiondata", type: .scalar(String.self)),

 public var reactiondata: String? {
        get {
          return resultMap["reactiondata"] as? String
        }
        set {
          resultMap.updateValue(newValue, forKey: "reactiondata")
        }
      }

The actual type from the schema file:

{ "name": "reactiondata", "description": null, "args": [], "type": { "kind": "SCALAR", "name": "Array", "ofType": null }, "isDeprecated": false, "deprecationReason": null },

If I am try with --passthroughCustomScalars Also I am geting error.

The resulting API.swift that was generated with --passthroughCustomScalars

public typealias Array = [AnyObject]

GraphQLField("reactiondata", type: .scalar(Array.self)),

public var reactiondata: Array? { get { return resultMap["reactiondata"] as? Array } set { resultMap.updateValue(newValue, forKey: "reactiondata") } }

I am geting following error.
Screenshot 2019-03-28 at 12 13 22 PM
Screenshot 2019-03-28 at 12 13 13 PM


`# Type a script or drag a script file from your workspace to insert its path.
APOLLO_FRAMEWORK_PATH="$(eval find $FRAMEWORK_SEARCH_PATHS -name "Apollo.framework" -maxdepth 1)"

if [ -z "$APOLLO_FRAMEWORK_PATH" ]; then
echo "error: Couldn't find Apollo.framework in FRAMEWORK_SEARCH_PATHS; make sure to add the framework to your project."
exit 1
fi

cd "${SRCROOT}/${TARGET_NAME}"
$APOLLO_FRAMEWORK_PATH/check-and-run-apollo-cli.sh codegen:generate --queries="$(find . -name '*.graphql')" --passthroughCustomScalars --schema=schema.json API.swift

Please let me know if I am going wrong somewhere

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024

@niraj1991 The type in the schema you posted seems to be a custom scalar called Array, not an actual GraphQL list type. If reactiondata is meant to be represented as an array, you should change the type in the schema.

from apollo-ios.

niraj1991 avatar niraj1991 commented on July 23, 2024

@martijnwalraven Thanks for writing to me.
I am updating my above post. can you please check again?

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024

@niraj1991 You'll have to change reactiondata to be an actual list in your schema, not a scalar. You can't generate a scalar with the name Array and expect it to map to a Swift Array.

from apollo-ios.

niraj1991 avatar niraj1991 commented on July 23, 2024

@martijnwalraven I changed the schema file like below.

{ "name": "details", "description": null, "args": [], "type": { "kind": "SCALAR", "name": "Json", "ofType": null }, "isDeprecated": false, "deprecationReason": null }

But I am Getting below error.

`Error at path "posts.0.reactiondata": couldNotConvert(value: <__NSArray0 0x600002408050>(
)
, to: Swift.Dictionary<Swift.String, Swift.Optional<Any>>)`

The resulting API.swift that was generated like below.

 public static let selections: [GraphQLSelection] = [
        GraphQLField("reactiondata", type: .scalar(Json.self)),
      ]
public var reactiondata: Json? {
        get {
          return resultMap["reactiondata"] as? Json
        }
        set {
          resultMap.updateValue(newValue, forKey: "reactiondata")
        }
      }

Also I am creating typealias like below.

public typealias Json = [String : Any?]

Let me know if you need any other details, I would be happy to share you.

Please let me know if I am going wrong somewhere.

Thanks in advance.

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024

@niraj1991 It seems you're returning an array from the server and trying to map this to a SwiftDictionary ([String : Any?]). If you need to use a JSON type (as opposed to changing the schema to something more specific), you'll have to use public typealias JSON = Any.

from apollo-ios.

niraj1991 avatar niraj1991 commented on July 23, 2024

@martijnwalraven if I am writing public typealias Json = Any Then I get the below error.
public typealias Json = Any

Screenshot 2019-03-28 at 6 31 22 PM

Here is schema file.

       {
            "name": "reactiondata",
            "description": null,
            "args": [],
            "type": {
              "kind": "SCALAR",
              "name": "Json",
              "ofType": null
            },
            "isDeprecated": false,
            "deprecationReason": null
          },

Please let me know if I need to change anything.

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024

@niraj1991 Ah, my mistake, I don't think Any is supported as a custom scalar type. Honestly, this doesn't seem like a great use case for custom scalars, you should really give reactiondata a proper type.

from apollo-ios.

JakeTorres avatar JakeTorres commented on July 23, 2024

Sript phase: SCRIPT_PATH="${PODS_ROOT}/Apollo/scripts"
cd "${SRCROOT}/${TARGET_NAME}"
"${SCRIPT_PATH}"/check-and-run-apollo-cli.sh codegen:generate --target=swift --includes=./**/*.graphql --passthroughCustomScalars --localSchemaFile="schema.json" API.swift

I do it in: JSONStandardTypeConversions
typealias Long = Int64
extension Long: JSONDecodable, JSONEncodable {
public init(jsonValue value: JSONValue) throws {
guard let number = value as? NSNumber else {
throw JSONDecodingError.couldNotConvert(value: value, to: Int64.self)
}
self = number.int64Value
}

public var jsonValue: JSONValue {
    return self
}

}

but run API.Swift get an error: Use of unresolved identifier 'Long'

who can tell me what wrong with that?

from apollo-ios.

designatednerd avatar designatednerd commented on July 23, 2024

Int support for custom scalars has (finally) shipped in 0.14.0.

@JakeTorres Can you please take your question to our Spectrum chat? it's not quite related to this issue. Thank you!

from apollo-ios.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.