You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
stringifyRequestData: (data)=>{return(qs.stringify(data,{serializeDate: (d)=>Math.floor(d.getTime()/1000),})// Don't use strict form encoding by changing the square bracket control// characters back to their literals. This is fine by the server, and// makes these parameter strings easier to read..replace(/%5B/g,'[').replace(/%5D/g,']'));},
{service: "stripe",name: "rest:post",parameters: [{// overriding the default stylein: "searchParams",name: "date_between",style: "pipeDelimited",mapping: [["get",{path: "args.date_between"}]],},{// demonstrating this is same as our current directive pipelinein: "searchParams",name: "dinner",mapping: [["get",{path: "args.random.fish"}],["toLowerCase",{}],],},{// simple examplein: "path",name: "account",mapping: [["get",{path: "claims.sub"}]],},{// using root indicator '$', a sort will place this first so we'll effectively extend (if value is an object) this with later valuesin: "form",name: "$",mapping: [["get",{path: "args.random"}]],},{// going to nest an object then extend itin: "form",name: "nested_and_extended",mapping: [["get",{path: "args.random"}]],},{// override explode and style settings, `nested_and_extended` will be extended rather than overwritten if it is an extendable type (Object)in: "form",name: "nested_and_extended",objectExtend: true,explode: false,style: "form",mapping: [["get",{path: "args.list_items[0]"}]],},{// array push notation, irrelevant here, but important on the next onein: "form",name: "line_items",mapping: [["get",{path: "args.line_items"}]],},{// array push option here prevents overwriting `line_items`. Returned array will be concatenated, anything else will be pushed. If the existing value is not an array it will be overwritten with the array output of this.in: "form",name: "line_items",arrayPush: true,mapping: [["get",{path: "args.random"}]],},{// this name syntax allows setting a property on each item in the array, this may not be a good idea (perhaps should be handled as a special directive)in: "form",name: "line_items[].coupon",mapping: [["set",{value: "COUPON_CODE"}]],},{// override default style and explodein: "form",name: "mode",style: "form",explode: false,value: ["subscription","one-off"],},{// override style and nested object notationin: "form",name: "deep.path",style: "form",explode: false,value: "SPINDRIFT",},{// our existing Stripe examplein: "form",name: "expand",mapping: [["get",{path: "args.expand"}]],},{// our existing Stripe examplein: "form",name: "expand",arrayPush: true,value: "field_i_really_want",},],parametersOptions: {form: {style: "deepObject",explode: true,},path: {style: "simple",},searchParams: {style: "deepObject",explode: true,},},}
parameters uses a new config format, moving away from tuples to arrays of config options
parametersOptions has broad configuration options for how parameters are used. These pertain to serialization style and formatting. They are effectively defaults, which any individual parameter can override.
The special parameter name $ referring to the root of the hypothetical object representation of the parameter.
value which allows you to directly set (in the schema) the value of a key
mapping which evaluates an array of directives to get a value
objectExtend and arrayPush as explicit operations — presumably these could be set as default behaviors via the parametersOptions.
Extended use case
With this new format it becomes possible to do batch operations, say we had an earlier resolver return a
list and we want to iterate over a particular property.
{service: "stripe",name: "rest:batch:get",parameters: [{in: "searchParams",name: "expand",value: ["prices","invoices"],},{// batchKey identifies this as the parameter to iterate over to make multiple requests, schema validation could enforce having only one of thesein: "path",name: "product",batchKey: true,mapping: [["jsonPath",{path: "steps.listCustomerProducts.data.items[*].productId"},],],},],}
{service: "stripe",name: "rest:post",searchParams: {ops: [{op: "set",// the default, doesn't need to be specificpath: "date_between",mapping: [["get",{path: "args.date_between"}]],},{path: "dinner",mapping: [["get",{path: "args.random.fish"}],["toLowerCase",{}],],},],serialize: {date_between: {style: "pipeDelimited",},},},pathParams: {ops: [{path: "account",mapping: [["get",{path: "claims.sub"}]],},],},form: {ops: [{path: "$",mapping: [["get",{path: "args.random"}]],},{// Example of the flexibility of the `ops` approach, we can extend a base object, then remove props we might not wantop: "remove",path: "price",mapping: [["get",{path: "args.random"}]],},{// extend will coerce this to an object, e.g., if args.random = 'foo' `nested_and_extended: { foo: 'foo' }`op: "extend",path: "nested_and_extended",mapping: [["get",{path: "args.random"}]],},{// object coercion and then object extend — basically the op ensures an object in the outputop: "extend",path: "nested_and_extended",mapping: [["get",{path: "args.list_items[0]"}]],},{// If we explicitly set the empty brackets, coerce any result to an array.path: "line_items[]",// OR, maybe we use these two and avoid custom syntaxop: "push",path: "line_items",mapping: [["get",{path: "args.line_items"}]],},{/* This is how we handle the concat/push behavior, similar to: * { line_items: [...args.line_items, isArray(args.random) ? ...args.random : args.random] } **/path: "line_items[]",// ORop: "push",path: "line_items",mapping: [["get",{path: "args.random"}]],},{// Syntax, inspired by jsonpath-plus, for operating on every item in an arraypath: "line_items[*].coupon",// This one trips me up, as I can't think of a "boring" syntax for describing thismapping: [["set",{value: "COUPON_CODE"}]],},{path: "mode",value: ["subscription","one-off"],},{path: "deep.path",value: "SPINDRIFT",},{path: "expand[]",mapping: [["get",{path: "args.expand"}]],},{path: "expand[]",value: "field_i_really_want",},],serialize: {nested_and_extended: {explode: false,style: "form"},mode: {explode: false,style: "form"},deep: {explode: false,style: "form"},expand: {explode: true,style: "deepObject"},},},}
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Also objectExtend: true and arrayPush: true feel like they should be the defaults or there should be an op: 'set' | 'push' | 'extend' property on each line and we'd change the set: [..] key to ops: [..]
The split out by section definitely looks more readable and maybe more easily validated, though it could lead to more schema churn. We'd need to support different prop names based on the capabilities of the resolver as opposed to adding to the enums of a single prop, e.g., in: 'form' | 'path' | 'searchParams' is added to, but we maintain a fairly generic / consistent parameters object. I have no strong opinion on this point, just highlighting.
I would still avoid tuples (sadly); the object format at the param level is capturing detail you haven't brought into the tuples, like the ability to set extend / push behaviors without necessarily creating a new language conveyed through the keys. I also think it is visually a bit easier to handle.
I think it makes sense to keep the keys as simple as possible, to avoid creating an ad-hoc language which is also challenging to validate... With your approach of having an explicit set child property, I wonder if it makes sense to support nesting of functionality:
varargs={foo: [{price: '100'},{price: '200}], bar: 'BAR'
}
Also objectExtend: true and arrayPush: true feel like they should be the defaults or there should be an op: 'set' | 'push' | 'extend' property on each line and we'd change the set: [..] key to ops: [..]
I don't quite follow this. Could you flesh out an example?
Also objectExtend: true and arrayPush: true feel like they should be the defaults or there should be an op: 'set' | 'push' | 'extend' property on each line and we'd change the set: [..] key to ops: [..]
I don't quite follow this. Could you flesh out an example?
constresolverConfig={"service": "stripe","name": "rest:post","searchParams": {"ops": [{"name": "date_between","mapping": [["get",{"path": "args.date_between"}]]},{"name": "dinner","mapping": [["get",{"path": "args.random.fish"}],["toLowerCase",{}]]}],"serialize": {"date_between": {"style": "pipeDelimited"}}},"pathParams": [{// simple example"name": "account","mapping": [["get",{"path": "claims.sub"}]]}],"form": {"ops": [{// going to nest an object then extend it"name": "nested_and_extended","mapping": [["get",{"path": "args.random"}]]},{// override explode and style settings, `nested_and_extended` will be extended rather than overwritten if it is an extendable type (Object)"name": "nested_and_extended","op": "extend","mapping": [["get",{"path": "args.list_items[0]"}]]},{// array push notation, irrelevant here, but important on the next one"name": "line_items","mapping": [["get",{"path": "args.line_items"}]]},{// array push option here prevents overwriting `line_items`. Returned array will be concatenated, anything else will be pushed. If the existing value is not an array it will be overwritten with the array output of this."name": "line_items","op": "push","mapping": [["get",{"path": "args.random"}]]},{// this name syntax allows setting a property on each item in the array, this may not be a good idea (perhaps should be handled as a special directive)"name": "line_items[].coupon","mapping": [["set",{"value": "COUPON_CODE"}]]},{// override default style and explode"name": "mode","value": ["subscription","one-off"]},{// override style and nested object notation"name": "deep.path","value": "SPINDRIFT"},{// our existing Stripe example"name": "expand","mapping": [["get",{"path": "args.expand"}]]},{// our existing Stripe example"name": "expand","op": "push","value": "field_i_really_want"}],"serialize": {"nested_and_extended": {"explode": false,"style": "form"},"mode": {"explode": false,"style": "form"},"deep": {"explode": false,"style": "form"}}}}
Also
objectExtend: true
andarrayPush: true
feel like they should be the defaults or there should be anop: 'set' | 'push' | 'extend'
property on each line and we'd change theset: [..]
key toops: [..]