Comlink Map

Version 2023.01.16

Introduction

Comlink Map is a format for describing one concrete implementation of a Comlink Profile. It essentially maps the application (business) semantics into provider’s interface implementation.

1Map Document

Defines a document that maps a profile into a particular provider’s API. At minimum, the map document consists of the profile and provider identifiers and a profile use‐case map.

Optionally, map document may specify a variant. Variant allows for mutliple maps for the same MapProfileIdentifier and ProviderIdentifier.

Example № 1profile = "conversation/send-message"
provider = "some-telco-api"

map SendMessage {
  ...
}

map RetrieveMessageStatus {
  ...
}
Example № 2profile = "conversation/send-message"
provider = "some-telco-api"
variant = "my-bugfix"

map SendMessage {
  ...
}

map RetrieveMessageStatus {
  ...
}

2Usecase Map

Map
mapUsecaseName{MapSlotlistopt}
Context Variables

Map context variables :

  • input - User input as stated in the profile
Example № 3map RetrieveMessageStatus {  
  http GET "/chat-api/v2/messages/{input.messageId}/history" {
    response 200 "application/json" {
      map result {
        deliveryStatus = body.history[0].state
      }
    }
  } 
}

2.1Map Result

MapResult
returnoptmap resultConditionoptSetMapResultVariablesopt
Example № 4map GetWeather {
  map result {
    airTemperature = 42  # Sets the value returned to user
  }
}

2.2Map Error

MapError
returnoptmap errorConditionoptSetMapErrorVariablesopt
Example № 5map GetWeather {
  map error {
    title = "Location not found"
  }
}

3Operation

Context Variables

Operation context variables :

Example № 6operation CountArray {
  return {
    answer = "This is the count " + args.array.length
  }
}

3.1Operation Return

Example № 7operation Foo {
  return if (args.condition) {
    message = "I have a condition!"
  }

  return {
    message = "Hello World!"
  }
}

3.2Operation Fail

Example № 8operation Foo {
  fail if (args.condition) {
    errorMessage = "I have failed!"
  }
}

4Set Variables

LHS
VariableNameVariableKeyPathObjectVariablelistopt
VariableKeyPathObjectVariable
KeyNameObjectVariable
Example № 9set {
  variable = 42
}
Example № 10set if (true) {
  variable = 42
}
Example № 11set {
  variable.key = 42
}
Example № 12set {
  variable = call ConvertToCelsius(tempF = 100)
}

5Operation Call

Condition and iteration

When both Condition and Iteration are specified, the condition is evaluated for every element of the iteration.

Context Variables

OperationCallSlot context variables:

  • outcome.data - data as returned by the callee
  • outcome.error - error as returned by the callee
Example № 13operation Bar {
  set {
    variable = 42
  }

  call FooWithArgs(text = `My string ${variable}`, some = variable + 2) {
    return if (!outcome.error) {
      finalAnswer = "The final answer is " + outcome.data.answer
    }

    fail if (outcome.error) {
      finalAnswer = "There was an error " + outcome.error.message
    }
  }
}
Example № 14map RetrieveCustomers {
  // Local variables
  set {
    filterId = null
  }


  // Step 1
  call FindFilter(filterName = "my-superface-map-filter") if(input.since) {
    // conditional block for setting the variables
    set if (!outcome.error) {
      filterId = outcome.data.filterId
    }
  }

  // Step 2
  call CreateFilter(filterId = filterId) if(input.since && !filterId) {
    set if (!outcome.error) {
      filterId = outcome.data.filterId
    }
  }

  // Step 3
  call RetrieveOrganizations(filterId = filterId) {
    map result if (!outcome.error && outcome.data) {
      customers = outcome.data.customers
    }
  }

  // Step 4
  call Cleanup() if(filterId) {
    // ...
  }
}
Example № 15operation Baz {
  array = [1, 2, 3, 4]
  count = 0
  data = []

  call foreach(x of array) Foo(argument = x) if (x % 2) {
    count = count + 1
    data = data.concat(outcome.data)
  }
}
Note there is a convenient way to call operations in VariableStament. Using the OperationCallShorthand, the example above can be written as:
Example № 16operation Baz {
  array = [1, 2, 3, 4]
  data = call foreach(x of array) Foo(argument = x) if (x % 2)
  count = data.length
}

5.1Operation Call Shorthand

Used as RHS instead of ScriptExpression to invoke an Operation in‐place. In the case of success the operation outcome’s data is unbundled and returned by the call. See OperationCall context variable outcome.

Example № 17set {
  someVariable = call Foo()
}
Iteration and operation call shorthand

When an iteration is specified ther result of the OperationCallShorthand is always an array.

Example № 18operationOutcome = call SomeOperation()

users = call foreach(user of operationOutcome.users) Foo(user = user) if (operationOutcome)

// Intepretation: 
// `Foo` is called for every `user` of `operationOutcome.users` if the `operationOutcome` is truthy

superusers = call foreach(user of operationOutcome.users) Bar(user = user) if (user.super)

// Intepretation: 
// `Bar` is called for an `user` of `operationOutcome.users` if the `user.super` is truthy

6Outcome

Evaluation of a use‐case map or operation outcome. The outcome definition depends on its context. When specified in the Map context the outcome is defined as SetMapOutcome. When specified in the Operation context the outcome is defined as SetOperationOutcome.

6.1Map Outcome

Outcome in the Map context.

6.2Operation Outcome

Outcome in the Operation context.

7Network Operation

NetworkCall
GraphQLCall

8HTTP Call

HTTPMethod
GETHEADPOSTPUTDELETECONNECTOPTIONSTRACEPATCH
Example № 19map SendMessage {
  http POST "/chat-api/v2/messages" {
    request "application/json" {
      body {
        to = input.to
        channels = ['sms']
        sms.from = input.from
        sms.contentType = 'text'
        sms.text = input.text
      }
    }

    response 200 "application/json" {
      map result {
        messageId = body.messageId
      }
    }
  }
}

Example of HTTP call to a service other than the defaultService.

Example № 20http GET service2 "/users" {
  ...
}

8.1HTTP Transaction

8.2HTTP Security

Example № 21GET "/users" {
  security "api_key_scheme_id"

  response {
    ...
  }
}

If no other HTTPSecurity is provided, the default is none. Explicitly signify public endpoints as none as so.

Example № 22GET "/public-endpoint" {
  security none
  
  response {
    ...
  }
}

8.3HTTP Request

Example № 23http GET "/greeting" {
  request {
    query {
      myName = "John"
    }
  }
}
Example № 24http POST "/users" {
  request "application/json" {
    query {
      parameter = "Hello World!"
    }

    headers {
      "my-header" = 42
    }

    body {
      key = 1
    }
  }
}
Example № 25http POST "/users" {
  request "application/json" {
    body = [1, 2, 3]
  }
}

8.4HTTP Response

HTTPResponse
responseStatusCodeoptContentTypeoptContentLanguageopt{HTTPResponseSlotlistopt}
Context Variables

HTTPResponseSlot context variables :

  • statusCode - HTTP response status code parsed as number
  • headers - HTTP response headers in the form of object
  • body - HTTP response body parsed as JSON
Example № 26http GET "/" {
  response 200 "application/json" {
    map result {
      outputKey = body.someKey
    }
  }
}
Example № 27http POST "/users" {
  response 201 "application/json" {
    return {
      id = body.userId
    }
  }
}

Handling HTTP errors:

Example № 28http POST "/users" {
  response 201 "application/json" {
    ...
  }
  
  response 400 "application/json" {
    map error {
      title = "Wrong attributes"
      details = body.message
    }
  }
}

Handling business errors, status code is left out and the handler processes everything:

Example № 29http POST "/users" {
  response "application/json" {
    map result if (body.ok) {
      ...
    }

    map error if (!body.ok) {
      ...
    }
  }
}

When ContentType is not relevant but ContentLanguage is needed, use the * wildchar in place of the ContentType as follows:

Example № 30http GET "/" {
  response "*" "en-US" {
    map result {
      rawOutput = body
    }
  }
}

9Conditions

Conditional statement evalutess its ScriptExpression for truthiness.

Example № 31if ( true )
Example № 32if ( 1 + 1 )
Example № 33if ( variable % 2 )
Example № 34if ( variable.length == 42 )

10Iterations

When the given ScriptExpression evaluates to an array (or any other ECMA Script iterable), this statement iterates over its elements assigning the respective element value to its context VariableName variable.

Example № 35foreach (x of [1, 2, 3])
Example № 36foreach (element of variable.nestedArray)

11Script

This is a subset of the Javascript programming language designed to be familiar to a great number of programmers while reducing the possible attack surface of the runtime environment.

This specification is based on and references ECMA 262 and heavily inspired by Jessie.

11.1Operators

ScriptBinaryOperator
+-***/%&&||<<>>>>>&|^<><=>====!==
Note This omits the following operators which are defined in Javascript grammar: ++ -- == != %= <<= >>= >>>= &= |= ^=

11.2Literals

11.2.1Primitive

ScriptPrimitiveLiteral
One of the allowed Javascript literal productions

The allowed Javascript literal productions are:

Example № 371.234e-4
Example № 38"hello world"
Example № 39`Foo: ${foo}, bar: ${bar}`
Note This corresponds to NumericLiteral without DecimalBigIntegerLiteral.

11.2.2Array

Example № 40[...[1, 2], 3, 4]
Note This corresponds to ArrayLiteral without yield, await and Elision.

11.2.3Object

Example № 41{ ...a, b: 1, c: 2 + 3 }
Note This corresponds to ObjectLiteral without yield, await, CoverInitializedName, ComputedPropertyName and MethodDefinition.

11.3Identifiers

ScriptIdentifier
Javascript identifier production

Javascript identifier production

ScriptReservedWord
Javascript reserved word production

Javascript reserved word production

Note Reserved words that are not keywords cannot be used because they would conflict with the Javascript grammar.
ScriptKeyword
breakcaseconstcontinuedefaultdoelsefalse
forifnullreturnswitchtruewhile

11.4Expressions

Expressions are central to the script. Expressions appear on the right‐hand side of VariableStatement, in Conditions and in operation call Argument list.

Since the only way to obtain a lexical context in which statements can be declared is to create an ScriptArrowFunction, it is often more convenient to use functional patterns to transform data:

Example № 42Object.entries(foo).filter(
  ([_key, value]) => value > 0
).map(
  ([key, _value]) => key
)
Example № 431 + 2**input.exponent
Example № 44{ ...a, b: 1, c: 2 + 3, d: [...[1, 2], 3, 4] }
Example № 45(() => {
  const result = "only do this in very complex cases"
  return result
})()

11.4.1Unary

Example № 46-7

11.4.2Binary

Example № 47"foo" + "bar"
Example № 48foo.bar += 7 * 8

11.4.3Ternary

Example № 49foo === 1 ? "hello" : "goodbye"

11.4.4Call

Example № 50foo.bar(1, 2 + 3, ["hello", "world"])

11.5Binding patterns

Binding patterns are used when destructuring values in variable declarations and function parameter declarations (i.e. in ScriptArrowFunction).

ScriptBindingPattern
Javascript binding pattern production

Javascript binding pattern production: BindingPattern without yield, await, Elision and ComputedPropertyName.

Example № 51[a, b = 2, ...c]
Example № 52{ a, b = 2, c: x = 3, ...d }

11.6Arrow function

Arrow functions are the only way to declare callable items in the script. They can be passed to built‐in methods like Array.map or in the most complex cases used as immediately‐invoked function expressions (e.g. (() => 1)()).

ScriptArrowFunction
Javascript arrow function production
Example № 53([a, b, c = 1]) => { return a + b ** c; }
Note Javascript arrow function production: ArrowFunction without yield, await and where FunctionBody is replaced by ScriptStatementlistopt.

11.7Statements

Statements are usually not relevant in the script, as expressions should be preferred instead.

ScriptStatement
One of the allowed Javascript statement productions

The allowed Javascript statement productions have the following caveats recursively:

The allowed Javascript statement productions are:

Example № 54return 1;
Example № 55{
  let x = 1;
  for (const y of [1, 2, 3]) {
    x += y;
  }

  if (x == 7) {
    return null;
  }
}

12Language

12.1Source text

SourceCharacter
/[\u0009\u000A\u000D\u0020-\uFFFF]/

12.1.1Comments

Example № 56// This is a comment

12.1.2Line Terminators

LineTerminator
New Line (U+000A)
Carriage Return (U+000D)New Line (U+000A)
Carriage Return (U+000D)New Line (U+000A)

12.2Common Definitions

12.2.1Identifier

Identifier
/[_A-Za-z][_0-9A-Za-z]*/

12.2.2Profile Identifier

DocumentNameIdentifier
/[a-z][a-z0-9_-]*/

Identifier of a profile regardless its version.

Example № 57character-information
Example № 58starwars/character-information

12.2.3Full Profile Identifier

Fully disambiguated identifier of a profile including its exact version.

Example № 59character-information@2.0.0
Example № 60starwars/character-information@1.1.0

12.2.4Map Profile Identifier

Profile identifier used in maps does not include the patch number.

Example № 61starwars/character-information@1.1

12.2.5Provider Identifier

12.2.6Service Identifier

Service identifier form provider’s definition. Generally used for specifying a service base (host) URL.

12.2.7URL Value

URLValue
"URL"

12.2.8Security Scheme Identifier

References the security scheme found within a provider definition.

12.2.9String Value

12.2.10Integer Value

IntegerValue
/[0-9]+/

AAppendix: Keywords

§Index

  1. Argument
  2. ArgumentList
  3. ArgumentListContinued
  4. Comment
  5. CommentChar
  6. Condition
  7. ContentLanguage
  8. ContentType
  9. DocumentNameIdentifier
  10. EscapedCharacter
  11. FullProfileIdentifier
  12. HTTPBody
  13. HTTPBodyValueDefinition
  14. HTTPCall
  15. HTTPHeaders
  16. HTTPMethod
  17. HTTPRequest
  18. HTTPRequestBodyAssignment
  19. HTTPRequestSlot
  20. HTTPResponse
  21. HTTPResponseSlot
  22. HTTPSecurity
  23. HTTPStatusCode
  24. HTTPTransaction
  25. Identifier
  26. IntegerValue
  27. Iteration
  28. KeyName
  29. LHS
  30. LineTerminator
  31. MajorVersion
  32. Map
  33. MapDocument
  34. MapError
  35. MapProfileIdentifier
  36. MapResult
  37. MapSlot
  38. MinorVersion
  39. NetworkCall
  40. Operation
  41. OperationArguments
  42. OperationCall
  43. OperationCallShorthand
  44. OperationCallSlot
  45. OperationFail
  46. OperationName
  47. OperationReturn
  48. OperationSlot
  49. PatchVersion
  50. Profile
  51. ProfileIdentifier
  52. ProfileName
  53. ProfileScope
  54. Provider
  55. ProviderIdentifier
  56. RHS
  57. ScriptArrayLiteral
  58. ScriptArrayLiteralElement
  59. ScriptArrowFunction
  60. ScriptAssignmentExpression
  61. ScriptAssignmentOperator
  62. ScriptBinaryExpression
  63. ScriptBinaryOperator
  64. ScriptBindingPattern
  65. ScriptCallExpression
  66. ScriptExpression
  67. ScriptIdentifier
  68. ScriptKeyword
  69. ScriptLiteral
  70. ScriptObjectLiteral
  71. ScriptObjectLiteralAssignment
  72. ScriptPrimitiveLiteral
  73. ScriptReservedWord
  74. ScriptStatement
  75. ScriptTernaryExpression
  76. ScriptUnaryExpression
  77. ScriptUnaryOperator
  78. SecuritySchemeIdentifier
  79. SemanticVersion
  80. ServiceIdentifier
  81. SetMapErrorVariables
  82. SetMapOutcome
  83. SetMapResultVariables
  84. SetOperationFailVariables
  85. SetOperationOutcome
  86. SetOperationReturnVariables
  87. SetOutcome
  88. SetVariables
  89. SourceCharacter
  90. StringCharacter
  91. StringValue
  92. URLPath
  93. URLPathLiteral
  94. URLPathSegment
  95. URLPathVariable
  96. URLQuery
  97. URLTemplate
  98. URLValue
  99. UsecaseName
  100. VariableKeyPath
  101. VariableName
  102. VariableStatement
  103. VariableStatements
  104. Variant
  1. 1Map Document
  2. 2Usecase Map
    1. 2.1Map Result
    2. 2.2Map Error
  3. 3Operation
    1. 3.1Operation Return
    2. 3.2Operation Fail
  4. 4Set Variables
  5. 5Operation Call
    1. 5.1Operation Call Shorthand
  6. 6Outcome
    1. 6.1Map Outcome
    2. 6.2Operation Outcome
  7. 7Network Operation
  8. 8HTTP Call
    1. 8.1HTTP Transaction
    2. 8.2HTTP Security
    3. 8.3HTTP Request
    4. 8.4HTTP Response
  9. 9Conditions
  10. 10Iterations
  11. 11Script
    1. 11.1Operators
    2. 11.2Literals
      1. 11.2.1Primitive
      2. 11.2.2Array
      3. 11.2.3Object
    3. 11.3Identifiers
    4. 11.4Expressions
      1. 11.4.1Unary
      2. 11.4.2Binary
      3. 11.4.3Ternary
      4. 11.4.4Call
    5. 11.5Binding patterns
    6. 11.6Arrow function
    7. 11.7Statements
  12. 12Language
    1. 12.1Source text
      1. 12.1.1Comments
      2. 12.1.2Line Terminators
    2. 12.2Common Definitions
      1. 12.2.1Identifier
      2. 12.2.2Profile Identifier
      3. 12.2.3Full Profile Identifier
      4. 12.2.4Map Profile Identifier
      5. 12.2.5Provider Identifier
      6. 12.2.6Service Identifier
      7. 12.2.7URL Value
      8. 12.2.8Security Scheme Identifier
      9. 12.2.9String Value
      10. 12.2.10Integer Value
  13. AAppendix: Keywords
  14. §Index