ts2workflows 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -34,11 +34,13 @@ Map keys can be identifiers or strings: `{temperature: -12}` or `{"temperature":
34
34
 
35
35
  ### Bytes type
36
36
 
37
- It is not possible to construct a bytes object expect by calling a function that returns bytes (e.g. base64.decode). It is not possible to do anything else with a bytes object than to assign it to a variable and to pass it one of the functions that take bytes type as input variable (e.g. base64.encode).
37
+ A `bytes` object can only be constructed by calling a function that returns bytes (e.g. `base64.decode`). The only things that can be done with a `bytes` object is to assign it to variable and to pass the `bytes` object to one of the functions that take `bytes` type as input variable (e.g. `base64.encode`).
38
38
 
39
39
  ### null type
40
40
 
41
- In addition to the literal `null`, the Typescript `undefined` value is also treated as `null` in Workflows YAML.
41
+ In addition to the literal `null`, the Typescript `undefined` value is also translated to `null` in Workflows YAML.
42
+
43
+ Note that on Typescript-level typechecking `null` and `undefined` are considered distinct types.
42
44
 
43
45
  ### Implicit type conversions
44
46
 
@@ -79,6 +81,7 @@ sys.get_env('GOOGLE_CLOUD_PROJECT_ID')
79
81
  | ?? | nullish coalescing |
80
82
  | ?. | optional chaining |
81
83
  | ? : | conditional operator |
84
+ | typeof | return the type of the operand as a string |
82
85
 
83
86
  The [precendence order of operators](https://cloud.google.com/workflows/docs/reference/syntax/datatypes#order-operations) is the same as in GCP Workflows.
84
87
 
@@ -98,7 +101,7 @@ is converted to an [if() expression](https://cloud.google.com/workflows/docs/ref
98
101
  ${if(x > 0, "positive", "not positive")}
99
102
  ```
100
103
 
101
- ⚠️ Note that Workflows always evaluates both expression branches unlike Typescript which evaluates only the branch that gets executed.
104
+ ⚠️ Workflows always evaluates both expression branches unlike Typescript which evaluates only the branch that gets executed.
102
105
 
103
106
  ### Nullish coalescing operator
104
107
 
@@ -114,7 +117,7 @@ is converted to a [default() expression](https://cloud.google.com/workflows/docs
114
117
  ${default(x, "default value")}
115
118
  ```
116
119
 
117
- ⚠️ Note that Workflows always evaluates the right-hand side expression unlike Typescript which evaluates the right-hand side only if the left-hand side is `null` or `undefined`.
120
+ ⚠️ Workflows always evaluates the right-hand side expression unlike Typescript which evaluates the right-hand side only if the left-hand side is `null` or `undefined`.
118
121
 
119
122
  ### Optional chaining
120
123
 
@@ -130,11 +133,28 @@ is converted to a [map.get() expression](https://cloud.google.com/workflows/docs
130
133
  ${map.get(data, ["user", "name"])}
131
134
  ```
132
135
 
136
+ ### typeof operator
137
+
138
+ Returns the type of the operand as a string. The return values are the same ones that Javascript typeof operation returns. The following table shows the possible values for different operand types.
139
+
140
+ | Operand | Result |
141
+ | ------- | --------- |
142
+ | boolean | "boolean" |
143
+ | bytes | "object" |
144
+ | double | "number" |
145
+ | integer | "number" |
146
+ | list | "object" |
147
+ | map | "object" |
148
+ | string | "string" |
149
+ | null | "object" |
150
+
151
+ The typeof operator is useful as a type guard in Typescript (e.g. `typeof x === "string"`). For other use cases, consider the [get_type function](https://cloud.google.com/workflows/docs/reference/stdlib/expression-helpers#type_functions) from the Workflows standard library. It makes finer distinctions between types. It, for example, returns distinct values for lists and maps.
152
+
133
153
  ## Template literals
134
154
 
135
155
  Template literals are strings that support string interpolation. For example, `Hello ${name}`.
136
156
 
137
- ⚠️ Interpolated values can (only) be numbers, strings or booleans. Other types will throw a TypeError at runtime.
157
+ ⚠️ Interpolated values can (only) be numbers, strings, booleans or nulls. Other types will throw a TypeError at runtime.
138
158
 
139
159
  ## Subworkflow definitions
140
160
 
@@ -155,7 +175,7 @@ function anotherWorkflow(): number {
155
175
  }
156
176
  ```
157
177
 
158
- Workflows can have parameters:
178
+ Subworkflows can have parameters:
159
179
 
160
180
  ```typescript
161
181
  function multiply(firstFactor: number, secondFactor: number): number {
@@ -163,10 +183,18 @@ function multiply(firstFactor: number, secondFactor: number): number {
163
183
  }
164
184
  ```
165
185
 
166
- Parameters can be optional and have a default value that is used if a value is not provided in a subworkflow call:
186
+ Optional parameters can be specified with a question mark. If a value is not provided on the call site, the value is set to `null` during the subworkflow execution. The following subworkflow can be called as `greet()` or `greet("Tiabeanie")`.
187
+
188
+ ```typescript
189
+ function greet(name?: string): string {
190
+ return 'Hello, ${name ?? "world"}'
191
+ }
192
+ ```
193
+
194
+ Parameters can have default values. The default value is used if a value is not provided in a subworkflow call. The following subworkflow can be called with one parameter (`log(3)`) or with two parameters (`log(3, 2)`).
167
195
 
168
196
  ```typescript
169
- function log(x, base = 10) {
197
+ function log(x: number, base: number = 10) {
170
198
  return 'Should compute the logarithm of x'
171
199
  }
172
200
  ```
@@ -201,7 +229,7 @@ is converted to an [assign step](https://cloud.google.com/workflows/docs/referen
201
229
 
202
230
  This syntax can be used to call [standard library functions](https://cloud.google.com/workflows/docs/reference/stdlib/overview), subworkflows or connectors. Note that Javascript runtime functions (such as `fetch()`, `console.error()` or `new XMLHttpRequest()`) are not available on Workflows.
203
231
 
204
- GCP Workflows language has two ways of calling functions and subworkflows: as expression in an [assign step](https://cloud.google.com/workflows/docs/reference/syntax/variables#assign-step) or as [call step](https://cloud.google.com/workflows/docs/reference/syntax/calls). They can mostly be used interchangeably. However, [blocking calls](https://cloud.google.com/workflows/docs/reference/syntax/expressions#blocking-calls) must be made as call steps. The transpiler tries to automatically output a call step when necessary.
232
+ GCP Workflows language has two ways of calling functions and subworkflows: as expression in an [assign step](https://cloud.google.com/workflows/docs/reference/syntax/variables#assign-step) or as [call step](https://cloud.google.com/workflows/docs/reference/syntax/calls). They can mostly be used interchangeably. However, [blocking calls](https://cloud.google.com/workflows/docs/reference/syntax/expressions#blocking-calls) must be made as call steps. The ts2workflows transpiler tries to automatically output a call step when necessary.
205
233
 
206
234
  It is also possible to force a function to be called as call step. This might be useful, if the transpiler fails to output call step when it should, or if you want to use named parameters. For example, the following Typescript program
207
235
 
@@ -561,7 +589,7 @@ parallel(
561
589
  )
562
590
  ```
563
591
 
564
- ## Try/catch statements
592
+ ## Try/catch/finally statements
565
593
 
566
594
  The statement
567
595
 
@@ -592,13 +620,48 @@ is compiled to the following [try/except structure](https://cloud.google.com/wor
592
620
 
593
621
  The error variable and other variables created inside the catch block are accessible only in that block's scope (similar to [the variable scoping in Workflows](https://cloud.google.com/workflows/docs/reference/syntax/catching-errors#variable-scope)).
594
622
 
623
+ Finally block is also supported:
624
+
625
+ ```javascript
626
+ try {
627
+ return readFile()
628
+ } catch (err) {
629
+ return 'Error!'
630
+ } finally {
631
+ closeFile()
632
+ }
633
+ ```
634
+
635
+ If an exception gets thrown inside a try block, the stack trace in Workflows logs will misleadingly show the exception originating from inside the finally block. This happens because the implementation of the finally block catches the original exception and later throws an identical exception. The original source location of the exception is lost.
636
+
637
+ ⚠️ At the moment, break and continue are not supported in a try or a catch block if there is a related finally block.
638
+
595
639
  ## Retrying on errors
596
640
 
597
641
  It is possible to set a retry policy for a try-catch statement. Because Typescript does not have `retry` keyword, the retry is implemented by a special `retry_policy` function. It must be called immediately after a try-catch block. A call to the `retry_policy` is ignored elsewhere.
598
642
 
599
- The `retry_policy` function must be called with parameters defining a retry policy. It can be either a policy provided by GCP Workflows or a custom retry policy. See the GCP documentation for the [required parameters for the two policy types](https://cloud.google.com/workflows/docs/reference/syntax/retrying#try-retry).
643
+ Finally and catch blocks are run after possible retry attempts. The following sample retries `http.get()` if it throws an exception and executes `sys.log('Error!')` and `closeConnection()` after retry attempts.
600
644
 
601
- A sample with a GCP-provided retry policy:
645
+ ```javascript
646
+ import { http, retry_policy, sys } from 'ts2workflows/types/workflowslib'
647
+
648
+ function main() {
649
+ try {
650
+ http.get('https://visit.dreamland.test/')
651
+ } catch (err) {
652
+ sys.log('Error!')
653
+ } finally {
654
+ closeConnection()
655
+ }
656
+ retry_policy(http.default_retry)
657
+ }
658
+ ```
659
+
660
+ The `retry_policy` function must be called with a parameter that defines the retry policy. It can be either a policy provided by GCP Workflows or a custom retry policy.
661
+
662
+ ### GCP-provided retry policy
663
+
664
+ GCP retry policy must be either `http.default_retry` or `http.default_retry_non_idempotent`. Their effects are described by the [GCP documentation](https://cloud.google.com/workflows/docs/reference/syntax/retrying#default-retry-policy).
602
665
 
603
666
  ```javascript
604
667
  import { http, retry_policy } from 'ts2workflows/types/workflowslib'
@@ -609,11 +672,15 @@ function main() {
609
672
  } catch (err) {
610
673
  return 'Error!'
611
674
  }
612
- retry_policy({ policy: http.default_retry })
675
+ retry_policy(http.default_retry)
613
676
  }
614
677
  ```
615
678
 
616
- A sample with a custom retry policy:
679
+ ### Custom retry policy
680
+
681
+ A custom retry policy is an object with the properties shown in the following example. See the GCP documentation for the [explanation of the properties](https://cloud.google.com/workflows/docs/reference/syntax/retrying#try-retry).
682
+
683
+ The parameter must be a literal map object (not a variable). The values may be literals or expressions.
617
684
 
618
685
  ```javascript
619
686
  import { http, retry_policy } from 'ts2workflows/types/workflowslib'
@@ -699,7 +766,7 @@ is converted to a step with the label `setName`:
699
766
 
700
767
  ## Type annotations for standard library functions
701
768
 
702
- Type annotations for GCP Workflows standard library functions and expression helpers are provided by importing "ts2workflows/types/workflowslib".
769
+ Type annotations for [GCP Workflows standard library functions and expression helpers](https://cloud.google.com/workflows/docs/reference/stdlib/overview) are provided by importing "ts2workflows/types/workflowslib".
703
770
 
704
771
  ```typescript
705
772
  import { sys } from 'ts2workflows/types/workflowslib'
@@ -766,11 +833,9 @@ The `parallel` function executes code blocks in parallel (using [parallel step](
766
833
  ```typescript
767
834
  function retry_policy(
768
835
  params:
836
+ | ((errormap: Record<string, any>) => void)
769
837
  | {
770
- policy: (exception: unknown) => void
771
- }
772
- | {
773
- predicate: (exception: unknown) => boolean
838
+ predicate: (errormap: Record<string, any>) => boolean
774
839
  max_retries: number
775
840
  backoff: {
776
841
  initial_delay: number
@@ -781,7 +846,7 @@ function retry_policy(
781
846
  ): void
782
847
  ```
783
848
 
784
- The `retry_policy` function can called right after a `try`-`catch` block to specify a retry policy. See the section on retrying.
849
+ The `retry_policy` function can called right after a `try`-`catch` block to specify a retry policy. See the section on [retrying errors](#retrying-on-errors).
785
850
 
786
851
  ## Source code comments
787
852
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts2workflows",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Transpile Typescript code to GCP Workflows programs",
5
5
  "homepage": "https://github.com/aajanki/ts2workflows",
6
6
  "repository": {
@@ -66,7 +66,7 @@
66
66
  "eslint": "^9.10.0",
67
67
  "husky": "^9.1.6",
68
68
  "lint-staged": "^15.2.10",
69
- "mocha": "^10.4.0",
69
+ "mocha": "^11.1.0",
70
70
  "prettier": "^3.2.5",
71
71
  "rimraf": "^5.0.10",
72
72
  "tsx": "^4.10.2",
@@ -78,4 +78,4 @@
78
78
  "typescript": "^5.0.0",
79
79
  "yaml": "^2.4.2"
80
80
  }
81
- }
81
+ }
@@ -1,11 +1,13 @@
1
+ export {}
2
+
1
3
  // Type annotations for GCP Workflows expression helpers, standard library
2
4
  // functions and (some) connectors
3
5
 
4
6
  // An opaque bytes type.
5
7
  // This should really be defined in the transpiler, not here.
6
- declare const tag: unique symbol
8
+ declare const __bytes_tag: unique symbol
7
9
  export interface bytes {
8
- readonly [tag]: 'bytes'
10
+ readonly [__bytes_tag]: 'bytes'
9
11
  }
10
12
 
11
13
  // GCP Workflows expression helpers
@@ -37,25 +39,48 @@ export declare namespace base64 {
37
39
  }
38
40
 
39
41
  export declare namespace events {
40
- function await_callback(
42
+ function await_callback<ResponseType = unknown>(
41
43
  callback: {
42
44
  url: string
43
45
  },
44
46
  timeout?: number,
45
- ): object
47
+ ): {
48
+ http_request: {
49
+ body: ResponseType | null
50
+ headers: Record<string, string>
51
+ method: string
52
+ query: Record<string, string>
53
+ url: string
54
+ }
55
+ received_time: string
56
+ type: string
57
+ }
46
58
  function create_callback_endpoint(http_callback_method: string): {
47
59
  url: string
48
60
  }
49
61
  }
50
62
 
63
+ export declare namespace hash {
64
+ export function compute_checksum(data: bytes, algorithm: string): bytes
65
+ export function compute_hmac(
66
+ key: bytes,
67
+ data: bytes,
68
+ algorithm: string,
69
+ ): bytes
70
+ }
71
+
51
72
  export declare namespace http {
52
- export function default_retry(exception: unknown): void
53
- export function default_retry_non_idempotent(exception: unknown): void
54
- export function default_retry_predicate(exception: unknown): boolean
73
+ export function default_retry(errormap: Record<string, any>): void
74
+ export function default_retry_non_idempotent(
75
+ errormap: Record<string, any>,
76
+ ): void
77
+ export function default_retry_predicate(
78
+ errormap: Record<string, any>,
79
+ ): boolean
55
80
  export function default_retry_predicate_non_idempotent(
56
- exception: unknown,
81
+ errormap: Record<string, any>,
57
82
  ): boolean
58
- function _delete(
83
+ function _delete<ResponseType = unknown>(
59
84
  url: string,
60
85
  timeout?: number,
61
86
  body?: unknown,
@@ -68,11 +93,11 @@ export declare namespace http {
68
93
  private_service_name?: string,
69
94
  ca_certificate?: string,
70
95
  ): {
71
- body: unknown
96
+ body: ResponseType
72
97
  code: number
73
98
  headers: Record<string, string>
74
99
  }
75
- export function get(
100
+ export function get<ResponseType = unknown>(
76
101
  url: string,
77
102
  timeout?: number,
78
103
  headers?: Record<string, string>,
@@ -84,11 +109,11 @@ export declare namespace http {
84
109
  private_service_name?: string,
85
110
  ca_certificate?: string,
86
111
  ): {
87
- body: unknown
112
+ body: ResponseType
88
113
  code: number
89
114
  headers: Record<string, string>
90
115
  }
91
- export function patch(
116
+ export function patch<ResponseType = unknown>(
92
117
  url: string,
93
118
  timeout?: number,
94
119
  body?: unknown,
@@ -101,11 +126,11 @@ export declare namespace http {
101
126
  private_service_name?: string,
102
127
  ca_certificate?: string,
103
128
  ): {
104
- body: unknown
129
+ body: ResponseType
105
130
  code: number
106
131
  headers: Record<string, string>
107
132
  }
108
- export function post(
133
+ export function post<ResponseType = unknown>(
109
134
  url: string,
110
135
  timeout?: number,
111
136
  body?: unknown,
@@ -118,11 +143,11 @@ export declare namespace http {
118
143
  private_service_name?: string,
119
144
  ca_certificate?: string,
120
145
  ): {
121
- body: unknown
146
+ body: ResponseType
122
147
  code: number
123
148
  headers: Record<string, string>
124
149
  }
125
- export function put(
150
+ export function put<ResponseType = unknown>(
126
151
  url: string,
127
152
  timeout?: number,
128
153
  body?: unknown,
@@ -135,11 +160,11 @@ export declare namespace http {
135
160
  private_service_name?: string,
136
161
  ca_certificate?: string,
137
162
  ): {
138
- body: unknown
163
+ body: ResponseType
139
164
  code: number
140
165
  headers: Record<string, string>
141
166
  }
142
- export function request(
167
+ export function request<ResponseType = unknown>(
143
168
  method: string,
144
169
  url: string,
145
170
  timeout?: number,
@@ -153,7 +178,7 @@ export declare namespace http {
153
178
  private_service_name?: string,
154
179
  ca_certificate?: string,
155
180
  ): {
156
- body: unknown
181
+ body: ResponseType
157
182
  code: number
158
183
  headers: Record<string, string>
159
184
  }
@@ -169,7 +194,8 @@ export declare namespace json {
169
194
  | boolean
170
195
  | unknown[]
171
196
  | Record<string, unknown>
172
- | null,
197
+ | null
198
+ | undefined,
173
199
  indent?:
174
200
  | boolean
175
201
  | {
@@ -184,7 +210,8 @@ export declare namespace json {
184
210
  | boolean
185
211
  | unknown[]
186
212
  | Record<string, unknown>
187
- | null,
213
+ | null
214
+ | undefined,
188
215
  indent?:
189
216
  | boolean
190
217
  | {
@@ -233,7 +260,8 @@ export declare namespace retry {
233
260
  }
234
261
 
235
262
  export declare namespace sys {
236
- function get_env(name: string, default_value?: string): string | undefined
263
+ function get_env(name: string): string | null
264
+ function get_env(name: string, default_value: string): string
237
265
  function log(
238
266
  data?: number | boolean | string | unknown[] | object,
239
267
  severity?: string,
@@ -342,7 +370,7 @@ export declare namespace googleapis {
342
370
  interface Document {
343
371
  createTime: string
344
372
  fields: Record<string, Value>
345
- name: string
373
+ name?: string
346
374
  updateTime: string
347
375
  }
348
376
  interface DocumentMask {
@@ -553,7 +581,7 @@ export declare namespace googleapis {
553
581
  currentDocument?: Precondition
554
582
  delete?: string
555
583
  transform?: DocumentTransform
556
- update?: Document
584
+ update?: Pick<Document, 'fields' | 'name'>
557
585
  updateMask?: DocumentMask
558
586
  updateTransforms?: FieldTransform[]
559
587
  }
@@ -622,7 +650,7 @@ export declare namespace googleapis {
622
650
  export function createDocument(
623
651
  collectionId: string,
624
652
  parent: string,
625
- body: Document,
653
+ body: Pick<Document, 'fields' | 'name'>,
626
654
  documentId?: string,
627
655
  mask?: DocumentMask,
628
656
  ): Document
@@ -657,7 +685,7 @@ export declare namespace googleapis {
657
685
  currentDocument: Precondition,
658
686
  mask: DocumentMask,
659
687
  updateMask: DocumentMask,
660
- body: Document,
688
+ body: Pick<Document, 'fields' | 'name'>,
661
689
  ): Document
662
690
  export function rollback(
663
691
  database: string,
@@ -709,16 +737,14 @@ export declare function parallel(
709
737
 
710
738
  export declare function retry_policy(
711
739
  params:
740
+ | ((errormap: Record<string, any>) => void)
712
741
  | {
713
- policy: (exception: unknown) => void
714
- }
715
- | {
716
- predicate: (exception: unknown) => boolean
717
- max_retries: number
742
+ predicate?: (errormap: Record<string, any>) => boolean
743
+ max_retries?: number | string | null
718
744
  backoff: {
719
- initial_delay: number
720
- max_delay: number
721
- multiplier: number
745
+ initial_delay?: number | string | null
746
+ max_delay?: number | string | null
747
+ multiplier?: number | string | null
722
748
  }
723
749
  },
724
750
  ): void