@aloma.io/integration-sdk 3.8.68 → 3.8.70

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.
Files changed (44) hide show
  1. package/FINDINGS-PLAT-47.md +253 -0
  2. package/OPENAPI_TO_CONNECTOR.md +4 -1
  3. package/build/internal/fetcher/fetcher.d.mts +8 -0
  4. package/build/internal/fetcher/fetcher.mjs +47 -3
  5. package/build/openapi-to-connector.mjs +5 -2
  6. package/build/transform/index.d.mts +2 -2
  7. package/build/transform/index.mjs +493 -78
  8. package/package.json +3 -3
  9. package/src/internal/fetcher/fetcher.mts +52 -3
  10. package/src/openapi-to-connector.mts +6 -2
  11. package/src/transform/index.mts +530 -96
  12. package/test/fetcher-query-params.test.mjs +294 -0
  13. package/test/fixtures/transform/basic/expected.json +9 -0
  14. package/test/fixtures/transform/basic/src/controller/abstract.mts +5 -0
  15. package/test/fixtures/transform/basic/src/controller/index.mts +30 -0
  16. package/test/fixtures/transform/basic/tsconfig.json +1 -0
  17. package/test/fixtures/transform/interface-param/src/controller/abstract.mts +5 -0
  18. package/test/fixtures/transform/interface-param/src/controller/index.mts +12 -0
  19. package/test/fixtures/transform/interface-param/tsconfig.json +1 -0
  20. package/test/fixtures/transform/overloads/expected.json +6 -0
  21. package/test/fixtures/transform/overloads/src/controller/abstract.mts +5 -0
  22. package/test/fixtures/transform/overloads/src/controller/index.mts +11 -0
  23. package/test/fixtures/transform/overloads/tsconfig.json +1 -0
  24. package/test/fixtures/transform/tdd-stub/expected.json +8 -0
  25. package/test/fixtures/transform/tdd-stub/src/controller/abstract.mts +6 -0
  26. package/test/fixtures/transform/tdd-stub/src/controller/index.mts +204 -0
  27. package/test/fixtures/transform/tdd-stub/tsconfig.json +1 -0
  28. package/test/fixtures/transform/two-exports/src/controller/abstract.mts +5 -0
  29. package/test/fixtures/transform/two-exports/src/controller/index.mts +9 -0
  30. package/test/fixtures/transform/two-exports/tsconfig.json +1 -0
  31. package/test/fixtures/transform/type-error/src/controller/abstract.mts +5 -0
  32. package/test/fixtures/transform/type-error/src/controller/index.mts +7 -0
  33. package/test/fixtures/transform/type-error/tsconfig.json +1 -0
  34. package/test/fixtures/transform/typed/expected.json +8 -0
  35. package/test/fixtures/transform/typed/src/controller/abstract.mts +5 -0
  36. package/test/fixtures/transform/typed/src/controller/index.mts +13 -0
  37. package/test/fixtures/transform/typed/tsconfig.json +1 -0
  38. package/test/fixtures/transform/visibility/expected.json +9 -0
  39. package/test/fixtures/transform/visibility/src/controller/abstract.mts +5 -0
  40. package/test/fixtures/transform/visibility/src/controller/index.mts +19 -0
  41. package/test/fixtures/transform/visibility/tsconfig.json +1 -0
  42. package/test/openapi-to-connector.test.mts +7 -0
  43. package/test/transform.test.mjs +68 -0
  44. package/tools/mutation-run.mjs +23 -5
@@ -1,5 +1,43 @@
1
1
  import {unwrap} from '../util/index.mjs';
2
2
 
3
+ class ParamsError extends Error {}
4
+
5
+ /**
6
+ * build a query string from request params: undefined and null are skipped, arrays become repeated keys,
7
+ * objects are refused; values are encoded by URLSearchParams
8
+ */
9
+ const toQuery = (params: any): string => {
10
+ if (params == null) return '';
11
+ if (params instanceof URLSearchParams) return params.toString();
12
+ if (typeof params !== 'object' || Array.isArray(params)) throw new ParamsError('params must be an object');
13
+
14
+ const query = new URLSearchParams();
15
+ const add = (key: string, value: any) => {
16
+ if (value == null) return;
17
+ if (typeof value === 'object') {
18
+ throw new ParamsError(`params.${key} is an object; only strings, numbers, booleans and arrays of them are sent`);
19
+ }
20
+ query.append(key, String(value));
21
+ };
22
+
23
+ for (const [key, value] of Object.entries(params)) {
24
+ if (Array.isArray(value)) value.forEach((item) => add(key, item));
25
+ else add(key, value);
26
+ }
27
+
28
+ return query.toString();
29
+ };
30
+
31
+ const withQuery = (url: string, query: string): string => {
32
+ if (!query) return url;
33
+
34
+ const hash = url.indexOf('#');
35
+ const base = hash < 0 ? url : url.slice(0, hash);
36
+ const sep = !base.includes('?') ? '?' : /[?&]$/.test(base) ? '' : '&';
37
+
38
+ return base + sep + query + (hash < 0 ? '' : url.slice(hash));
39
+ };
40
+
3
41
  /**
4
42
  * http request fetcher
5
43
  */
@@ -73,6 +111,11 @@ export default class Fetcher {
73
111
  * request body like "hello world" or {hello: "world"}
74
112
  */
75
113
  body?: any;
114
+ /**
115
+ * query parameters like {limit: 10, properties: ["a", "b"]}, appended to the url;
116
+ * undefined and null are skipped, arrays become repeated keys, objects are refused
117
+ */
118
+ params?: {[key: string]: any} | URLSearchParams;
76
119
  },
77
120
  retries?: number,
78
121
  args: any = {}
@@ -95,6 +138,8 @@ export default class Fetcher {
95
138
  delete options0.url;
96
139
 
97
140
  theURL = !baseUrl ? url : `${baseUrl?.endsWith('/') ? baseUrl : baseUrl + '/'}${url}`.replace(/\/\/+/gi, '/');
141
+ // after the slash collapse, so encoded values are not altered; options0 keeps params for retries
142
+ const fullURL = withQuery(theURL, toQuery(options0.params));
98
143
 
99
144
  if (!options0?.headers || !options0?.headers?.Accept) {
100
145
  options0.headers = {
@@ -120,8 +165,9 @@ export default class Fetcher {
120
165
  }
121
166
 
122
167
  const timeout = Math.min(options0?.timeout || 30 * 60 * 1000, 30 * 60 * 1000);
123
- const ret = await fetch(theURL, {
124
- ...options0,
168
+ const {params, ...init} = options0;
169
+ const ret = await fetch(fullURL, {
170
+ ...init,
125
171
  signal: AbortSignal.timeout(timeout),
126
172
  });
127
173
  const status = await ret.status;
@@ -144,6 +190,8 @@ export default class Fetcher {
144
190
 
145
191
  return unwrap(ret, options0);
146
192
  } catch (e: any) {
193
+ if (e instanceof ParamsError) throw e;
194
+
147
195
  // too many requests
148
196
  if (e.status === 429) {
149
197
  return local.onError(e, url, options0, retries, args, true);
@@ -156,7 +204,8 @@ export default class Fetcher {
156
204
 
157
205
  --retries;
158
206
 
159
- console.log(theURL, e);
207
+ // without the query string: its values may hold ids or emails
208
+ console.log(theURL.split('?')[0], e);
160
209
 
161
210
  if (retries <= 0) throw e;
162
211
 
@@ -126,10 +126,14 @@ export class OpenAPIToConnector {
126
126
  const validationResult = OpenAPISchema.safeParse(parsed);
127
127
  if (!validationResult.success) {
128
128
  // Check if the errors are just about missing 'type' fields in schemas
129
- const criticalErrors = validationResult.error.errors.filter((err) => {
129
+ // zod 4 reports .issues (zod 3's .errors is gone), and a missing field is an invalid_type issue whose message no
130
+ // longer reads 'Required'
131
+ const isMissing = (err: any) =>
132
+ err.message.includes('Required') || (err.code === 'invalid_type' && /received undefined/.test(err.message));
133
+ const criticalErrors = validationResult.error.issues.filter((err) => {
130
134
  const path = err.path.join('.');
131
135
  // Allow missing 'type' in schema definitions as many OpenAPI specs don't include it
132
- return !path.includes('components.schemas') || !err.message.includes('Required');
136
+ return !path.includes('components.schemas') || !isMissing(err);
133
137
  });
134
138
 
135
139
  if (criticalErrors.length > 0) {