@seamapi/nextlove-sdk-generator 1.5.6 → 1.6.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.
Files changed (77) hide show
  1. package/lib/generate-csharp-sdk/codegen.d.ts +1 -0
  2. package/lib/generate-csharp-sdk/codegen.js +1 -0
  3. package/lib/generate-csharp-sdk/codegen.js.map +1 -1
  4. package/lib/generate-csharp-sdk/generate-csharp-sdk.js +10 -3
  5. package/lib/generate-csharp-sdk/generate-csharp-sdk.js.map +1 -1
  6. package/lib/generate-csharp-sdk/templates/dataclass.d.ts +1 -0
  7. package/lib/generate-csharp-sdk/templates/dataclass.js +46 -27
  8. package/lib/generate-csharp-sdk/templates/dataclass.js.map +1 -1
  9. package/lib/generate-php-sdk/generate-php-sdk.js +4 -4
  10. package/lib/generate-php-sdk/generate-php-sdk.js.map +1 -1
  11. package/lib/generate-python-sdk/class-file.js +4 -4
  12. package/lib/generate-python-sdk/class-file.js.map +1 -1
  13. package/lib/generate-python-sdk/generate-python-sdk.js +3 -4
  14. package/lib/generate-python-sdk/generate-python-sdk.js.map +1 -1
  15. package/lib/generate-ruby-sdk/generate-ruby-sdk.js +33 -14
  16. package/lib/generate-ruby-sdk/generate-ruby-sdk.js.map +1 -1
  17. package/lib/generate-ruby-sdk/ruby-client.d.ts +8 -2
  18. package/lib/generate-ruby-sdk/ruby-client.js +25 -6
  19. package/lib/generate-ruby-sdk/ruby-client.js.map +1 -1
  20. package/lib/generate-ruby-sdk/templates/.rspec.template.d.ts +2 -0
  21. package/lib/generate-ruby-sdk/templates/.rspec.template.js +4 -0
  22. package/lib/generate-ruby-sdk/templates/.rspec.template.js.map +1 -0
  23. package/lib/generate-ruby-sdk/templates/.ruby-version.template.d.ts +2 -0
  24. package/lib/generate-ruby-sdk/templates/.ruby-version.template.js +2 -0
  25. package/lib/generate-ruby-sdk/templates/.ruby-version.template.js.map +1 -0
  26. package/lib/generate-ruby-sdk/templates/base_resource.rb.template.js +2 -2
  27. package/lib/generate-ruby-sdk/templates/client.rb.template.d.ts +1 -1
  28. package/lib/generate-ruby-sdk/templates/client.rb.template.js +60 -73
  29. package/lib/generate-ruby-sdk/templates/client.rb.template.js.map +1 -1
  30. package/lib/generate-ruby-sdk/templates/request.rb.template.js +1 -1
  31. package/lib/generate-ruby-sdk/templates/resource_error.rb.template.js +2 -0
  32. package/lib/generate-ruby-sdk/templates/resource_error.rb.template.js.map +1 -1
  33. package/lib/generate-ruby-sdk/templates/resource_warning.rb.template.js +2 -0
  34. package/lib/generate-ruby-sdk/templates/resource_warning.rb.template.js.map +1 -1
  35. package/lib/generate-ruby-sdk/templates/seamapi.gemspec.template.js +2 -2
  36. package/lib/generate-ruby-sdk/templates/snippets/action-attempt-helpers-template.d.ts +2 -0
  37. package/lib/generate-ruby-sdk/templates/snippets/action-attempt-helpers-template.js +28 -0
  38. package/lib/generate-ruby-sdk/templates/snippets/action-attempt-helpers-template.js.map +1 -0
  39. package/lib/generate-ruby-sdk/templates/snippets/resource.rb.template.js +26 -7
  40. package/lib/generate-ruby-sdk/templates/snippets/resource.rb.template.js.map +1 -1
  41. package/lib/generate-ruby-sdk/templates/spec_helper.rb.template.d.ts +2 -0
  42. package/lib/generate-ruby-sdk/templates/spec_helper.rb.template.js +29 -0
  43. package/lib/generate-ruby-sdk/templates/spec_helper.rb.template.js.map +1 -0
  44. package/lib/generate-ruby-sdk/templates/support-helpers.rb.template.d.ts +2 -0
  45. package/lib/generate-ruby-sdk/templates/support-helpers.rb.template.js +12 -0
  46. package/lib/generate-ruby-sdk/templates/support-helpers.rb.template.js.map +1 -0
  47. package/lib/generate-ruby-sdk/templates/version.rb.template.js +1 -1
  48. package/lib/openapi/get-parameter-and-response-schema.d.ts +7 -0
  49. package/lib/openapi/get-parameter-and-response-schema.js +2 -0
  50. package/lib/openapi/get-parameter-and-response-schema.js.map +1 -1
  51. package/lib/openapi/map-parent-to-children-resource.d.ts +2 -2
  52. package/lib/openapi/map-parent-to-children-resource.js +2 -2
  53. package/lib/openapi/map-parent-to-children-resource.js.map +1 -1
  54. package/package.json +1 -1
  55. package/src/lib/generate-csharp-sdk/codegen.ts +1 -0
  56. package/src/lib/generate-csharp-sdk/generate-csharp-sdk.ts +24 -4
  57. package/src/lib/generate-csharp-sdk/templates/dataclass.ts +68 -46
  58. package/src/lib/generate-php-sdk/generate-php-sdk.ts +4 -4
  59. package/src/lib/generate-python-sdk/class-file.ts +4 -4
  60. package/src/lib/generate-python-sdk/generate-python-sdk.ts +3 -4
  61. package/src/lib/generate-ruby-sdk/generate-ruby-sdk.ts +47 -14
  62. package/src/lib/generate-ruby-sdk/ruby-client.ts +42 -7
  63. package/src/lib/generate-ruby-sdk/templates/.rspec.template.ts +3 -0
  64. package/src/lib/generate-ruby-sdk/templates/.ruby-version.template.ts +1 -0
  65. package/src/lib/generate-ruby-sdk/templates/base_resource.rb.template.ts +2 -2
  66. package/src/lib/generate-ruby-sdk/templates/client.rb.template.ts +62 -73
  67. package/src/lib/generate-ruby-sdk/templates/request.rb.template.ts +1 -1
  68. package/src/lib/generate-ruby-sdk/templates/resource_error.rb.template.ts +2 -0
  69. package/src/lib/generate-ruby-sdk/templates/resource_warning.rb.template.ts +2 -0
  70. package/src/lib/generate-ruby-sdk/templates/seamapi.gemspec.template.ts +2 -2
  71. package/src/lib/generate-ruby-sdk/templates/snippets/action-attempt-helpers-template.ts +27 -0
  72. package/src/lib/generate-ruby-sdk/templates/snippets/resource.rb.template.ts +34 -9
  73. package/src/lib/generate-ruby-sdk/templates/spec_helper.rb.template.ts +28 -0
  74. package/src/lib/generate-ruby-sdk/templates/support-helpers.rb.template.ts +11 -0
  75. package/src/lib/generate-ruby-sdk/templates/version.rb.template.ts +1 -1
  76. package/src/lib/openapi/get-parameter-and-response-schema.ts +2 -0
  77. package/src/lib/openapi/map-parent-to-children-resource.ts +2 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"support-helpers.rb.template.js","sourceRoot":"","sources":["../../../src/lib/generate-ruby-sdk/templates/support-helpers.rb.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;;;;;;IAUjB,CAAA"}
@@ -1,6 +1,6 @@
1
1
  export default () => `# frozen_string_literal: true
2
2
 
3
3
  module Seam
4
- VERSION = "1.11.2"
4
+ VERSION = "1.16.1"
5
5
  end`;
6
6
  //# sourceMappingURL=version.rb.template.js.map
@@ -4,12 +4,16 @@ export declare const getParameterAndResponseSchema: (route: Route) => {
4
4
  response_obj_type?: never;
5
5
  response_arr_type?: never;
6
6
  parameter_schema?: never;
7
+ response_schema?: never;
7
8
  res_return_schema?: never;
8
9
  } | {
9
10
  response_obj_type: undefined;
10
11
  response_arr_type: undefined;
11
12
  parameter_schema: ObjSchema;
12
13
  nullable: boolean;
14
+ response_schema: ObjSchema | {
15
+ oneOf: ObjSchema[];
16
+ };
13
17
  res_return_schema?: never;
14
18
  } | {
15
19
  response_obj_type: any;
@@ -17,4 +21,7 @@ export declare const getParameterAndResponseSchema: (route: Route) => {
17
21
  parameter_schema: ObjSchema;
18
22
  res_return_schema: ObjSchema | undefined;
19
23
  nullable: boolean;
24
+ response_schema: ObjSchema | {
25
+ oneOf: ObjSchema[];
26
+ };
20
27
  };
@@ -27,6 +27,7 @@ export const getParameterAndResponseSchema = (route) => {
27
27
  response_arr_type: undefined,
28
28
  parameter_schema,
29
29
  nullable,
30
+ response_schema,
30
31
  };
31
32
  }
32
33
  else {
@@ -36,6 +37,7 @@ export const getParameterAndResponseSchema = (route) => {
36
37
  parameter_schema,
37
38
  res_return_schema: res_return_schema,
38
39
  nullable,
40
+ response_schema,
39
41
  };
40
42
  }
41
43
  };
@@ -1 +1 @@
1
- {"version":3,"file":"get-parameter-and-response-schema.js","sourceRoot":"","sources":["../../src/lib/openapi/get-parameter-and-response-schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE1D,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,KAAY,EAAE,EAAE;IAC5D,MAAM,eAAe,GACnB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAEpE,MAAM,QAAQ,GAAG,CAAC,CAChB,eAAe;QACf,UAAU,IAAI,eAAe;QAC7B,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAC1E,CAAA;IAED,IAAI,CAAC,eAAe,EAAE;QACpB,OAAO,EAAE,QAAQ,EAAE,CAAA;KACpB;IAED,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE;QAC3B,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG;YACvB,OAAO,EAAE;gBACP,kBAAkB,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE;aACnE;SACK,CAAA;KACT;IAED,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE;QACzD,OAAO,EAAE,QAAQ,EAAE,CAAA;KACpB;IAED,MAAM,gBAAgB,GAAG,gBAAgB,CACvC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAC1D,CAAA;IACD,MAAM,iBAAiB,GAAI,eAAuB,CAAC,UAAU,CAC3D,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CACtC,CAAA;IAED,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,IAAI,CAAA;IAChD,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,KAAK,EAAE,IAAI,CAAA;IAEvD,IAAI,CAAC,gBAAgB,IAAI,CAAC,gBAAgB,EAAE;QAC1C,OAAO;YACL,iBAAiB,EAAE,SAAS;YAC5B,iBAAiB,EAAE,SAAS;YAC5B,gBAAgB;YAChB,QAAQ;SACT,CAAA;KACF;SAAM;QACL,OAAO;YACL,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE;YACtD,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE;YACtD,gBAAgB;YAChB,iBAAiB,EAAE,iBAA0C;YAC7D,QAAQ;SACT,CAAA;KACF;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"get-parameter-and-response-schema.js","sourceRoot":"","sources":["../../src/lib/openapi/get-parameter-and-response-schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE1D,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,KAAY,EAAE,EAAE;IAC5D,MAAM,eAAe,GACnB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAEpE,MAAM,QAAQ,GAAG,CAAC,CAChB,eAAe;QACf,UAAU,IAAI,eAAe;QAC7B,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAC1E,CAAA;IAED,IAAI,CAAC,eAAe,EAAE;QACpB,OAAO,EAAE,QAAQ,EAAE,CAAA;KACpB;IAED,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE;QAC3B,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG;YACvB,OAAO,EAAE;gBACP,kBAAkB,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE;aACnE;SACK,CAAA;KACT;IAED,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE;QACzD,OAAO,EAAE,QAAQ,EAAE,CAAA;KACpB;IAED,MAAM,gBAAgB,GAAG,gBAAgB,CACvC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAC1D,CAAA;IACD,MAAM,iBAAiB,GAAI,eAAuB,CAAC,UAAU,CAC3D,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CACtC,CAAA;IAED,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,IAAI,CAAA;IAChD,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,KAAK,EAAE,IAAI,CAAA;IAEvD,IAAI,CAAC,gBAAgB,IAAI,CAAC,gBAAgB,EAAE;QAC1C,OAAO;YACL,iBAAiB,EAAE,SAAS;YAC5B,iBAAiB,EAAE,SAAS;YAC5B,gBAAgB;YAChB,QAAQ;YACR,eAAe;SAChB,CAAA;KACF;SAAM;QACL,OAAO;YACL,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE;YACtD,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE;YACtD,gBAAgB;YAChB,iBAAiB,EAAE,iBAA0C;YAC7D,QAAQ;YACR,eAAe;SAChB,CAAA;KACF;AACH,CAAC,CAAA"}
@@ -1,3 +1,3 @@
1
1
  import type { Route } from "../../lib/types.js";
2
- declare const mapParentToChildrenResources: (routes: Route[]) => Record<string, string[]>;
3
- export default mapParentToChildrenResources;
2
+ declare const mapParentToChildResources: (routes: Route[]) => Record<string, string[]>;
3
+ export default mapParentToChildResources;
@@ -1,4 +1,4 @@
1
- const mapParentToChildrenResources = (routes) => routes.reduce((acc, route) => {
1
+ const mapParentToChildResources = (routes) => routes.reduce((acc, route) => {
2
2
  if (!route.post?.["x-fern-sdk-group-name"])
3
3
  return acc;
4
4
  const [parent_resource_name, child_resource_name] = route.post["x-fern-sdk-group-name"];
@@ -13,5 +13,5 @@ const mapParentToChildrenResources = (routes) => routes.reduce((acc, route) => {
13
13
  }
14
14
  return acc;
15
15
  }, {});
16
- export default mapParentToChildrenResources;
16
+ export default mapParentToChildResources;
17
17
  //# sourceMappingURL=map-parent-to-children-resource.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"map-parent-to-children-resource.js","sourceRoot":"","sources":["../../src/lib/openapi/map-parent-to-children-resource.ts"],"names":[],"mappings":"AAEA,MAAM,4BAA4B,GAAG,CACnC,MAAe,EACW,EAAE,CAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,GAA6B,EAAE,KAAK,EAAE,EAAE;IACrD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,uBAAuB,CAAC;QAAE,OAAO,GAAG,CAAA;IAEtD,MAAM,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,GAC/C,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAA;IAErC,IAAI,CAAC,oBAAoB;QAAE,OAAO,GAAG,CAAA;IAErC,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE;QAC9B,GAAG,CAAC,oBAAoB,CAAC,GAAG,EAAE,CAAA;KAC/B;IAED,IACE,mBAAmB;QACnB,CAAC,GAAG,CAAC,oBAAoB,CAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EACzD;QACA,GAAG,CAAC,oBAAoB,CAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;KACrD;IAED,OAAO,GAAG,CAAA;AACZ,CAAC,EAAE,EAAE,CAAC,CAAA;AAER,eAAe,4BAA4B,CAAA"}
1
+ {"version":3,"file":"map-parent-to-children-resource.js","sourceRoot":"","sources":["../../src/lib/openapi/map-parent-to-children-resource.ts"],"names":[],"mappings":"AAEA,MAAM,yBAAyB,GAAG,CAAC,MAAe,EAA4B,EAAE,CAC9E,MAAM,CAAC,MAAM,CAAC,CAAC,GAA6B,EAAE,KAAK,EAAE,EAAE;IACrD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,uBAAuB,CAAC;QAAE,OAAO,GAAG,CAAA;IAEtD,MAAM,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,GAC/C,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAA;IAErC,IAAI,CAAC,oBAAoB;QAAE,OAAO,GAAG,CAAA;IAErC,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE;QAC9B,GAAG,CAAC,oBAAoB,CAAC,GAAG,EAAE,CAAA;KAC/B;IAED,IACE,mBAAmB;QACnB,CAAC,GAAG,CAAC,oBAAoB,CAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EACzD;QACA,GAAG,CAAC,oBAAoB,CAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;KACrD;IAED,OAAO,GAAG,CAAA;AACZ,CAAC,EAAE,EAAE,CAAC,CAAA;AAER,eAAe,yBAAyB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seamapi/nextlove-sdk-generator",
3
- "version": "1.5.6",
3
+ "version": "1.6.0",
4
4
  "description": "Utilities for building NextLove SDK Generators",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -304,6 +304,7 @@ class TokenNode extends CSharpNode {
304
304
  static readonly TYPE_OBJECT = new TokenNode("object")
305
305
  static readonly TYPE_OBJECT_CLASS = new TokenNode("Object")
306
306
  static readonly TYPE_JOBJECT = new TokenNode("JObject")
307
+ static readonly TYPE_VOID = new TokenNode("void")
307
308
 
308
309
  constructor(
309
310
  public token: string,
@@ -54,12 +54,31 @@ export const generateCSharpSDK = async (
54
54
  group_names.reverse()
55
55
  const class_name = pascalCase(group_names.join("_"))
56
56
 
57
- const { parameter_schema, response_obj_type, response_arr_type, nullable } =
58
- getParameterAndResponseSchema(route)
57
+ const {
58
+ parameter_schema,
59
+ response_obj_type,
60
+ response_arr_type,
61
+ nullable,
62
+ response_schema,
63
+ } = getParameterAndResponseSchema(route)
64
+
65
+ let is_void = false
59
66
 
60
67
  if (!response_obj_type && !response_arr_type) {
61
- console.log(`No response object/array ref for "${route.path}", skipping`)
62
- continue
68
+ if (
69
+ !response_schema ||
70
+ "oneOf" in response_schema ||
71
+ Object.keys(response_schema.properties).filter(
72
+ (k) => k.toLowerCase() !== "ok"
73
+ ).length > 0
74
+ ) {
75
+ console.log(
76
+ `No response object/array ref for "${route.path}", skipping`
77
+ )
78
+ continue
79
+ }
80
+
81
+ is_void = true
63
82
  }
64
83
 
65
84
  if (!parameter_schema) {
@@ -73,6 +92,7 @@ export const generateCSharpSDK = async (
73
92
  parameter_schema,
74
93
  response_obj_type,
75
94
  response_arr_type,
95
+ is_void,
76
96
  return_path: route.post["x-fern-sdk-return-value"],
77
97
  namespace,
78
98
  nullable,
@@ -19,6 +19,7 @@ export type RouteInfo = {
19
19
  parameter_schema: ObjSchema
20
20
  response_obj_type: string | undefined
21
21
  response_arr_type: string | undefined
22
+ is_void: boolean
22
23
  nullable: boolean
23
24
  return_path: string
24
25
  namespace: string[]
@@ -155,6 +156,7 @@ export const generateDataclassFileForRoutes = (
155
156
  parameter_schema,
156
157
  return_path,
157
158
  nullable,
159
+ is_void,
158
160
  } = route
159
161
 
160
162
  const request = generateDataclassesForObjectOrRefSchema(
@@ -163,36 +165,40 @@ export const generateDataclassFileForRoutes = (
163
165
  "request"
164
166
  )
165
167
 
166
- if (!response_obj_type && !response_arr_type) {
168
+ if (!response_obj_type && !response_arr_type && !is_void) {
167
169
  // TODO: support non-named response types
168
170
  throw new Error("Invalid response type")
169
171
  }
170
172
 
171
- const responseType = new cs.TypeNode(
172
- response_arr_type
173
- ? new cs.TokenNodeGeneric("List", [
174
- new cs.TypeNode(
175
- new cs.TokenNode(pascalCase(response_arr_type)),
176
- nullable
177
- ),
178
- ])
179
- : new cs.TokenNode(pascalCase(response_obj_type!), nullable)
180
- )
173
+ const responseType = is_void
174
+ ? new cs.TypeNode(cs.TokenNode.TYPE_VOID)
175
+ : new cs.TypeNode(
176
+ response_arr_type
177
+ ? new cs.TokenNodeGeneric("List", [
178
+ new cs.TypeNode(
179
+ new cs.TokenNode(pascalCase(response_arr_type)),
180
+ nullable
181
+ ),
182
+ ])
183
+ : new cs.TokenNode(pascalCase(response_obj_type!), nullable)
184
+ )
181
185
 
182
- const response = generateDataclassesForSchema(
183
- pascalCase([method_name, "response"].join("_")),
184
- {
185
- type: "object",
186
- required: [],
187
- properties: {
188
- [pascalCase(return_path)]: {
189
- $ref: responseType.serialize(new cs.CompilerCtx()),
190
- nullable,
186
+ const response = is_void
187
+ ? undefined
188
+ : generateDataclassesForSchema(
189
+ pascalCase([method_name, "response"].join("_")),
190
+ {
191
+ type: "object",
192
+ required: [],
193
+ properties: {
194
+ [pascalCase(return_path)]: {
195
+ $ref: responseType.serialize(new cs.CompilerCtx()),
196
+ nullable,
197
+ },
198
+ },
191
199
  },
192
- },
193
- },
194
- "response"
195
- )
200
+ "response"
201
+ )
196
202
 
197
203
  const requestOptions = new cs.TokenNode("requestOptions")
198
204
  const requestObj = new cs.TokenNode("request")
@@ -209,12 +215,16 @@ export const generateDataclassFileForRoutes = (
209
215
  ? new cs.TypeNode(
210
216
  new cs.TokenNode("Task"),
211
217
  undefined,
212
- new cs.TypeArgumentsNode([type])
218
+ is_void ? undefined : new cs.TypeArgumentsNode([type])
213
219
  )
214
220
  : type
215
221
 
216
- const wrapAwait = (node: cs.CSharpNode) =>
217
- isAsync ? new cs.ParanthesisNode(new cs.AwaitNode(node)) : node
222
+ const wrapAwait = (node: cs.CSharpNode, parens = true) =>
223
+ isAsync
224
+ ? parens
225
+ ? new cs.ParanthesisNode(new cs.AwaitNode(node))
226
+ : new cs.AwaitNode(node)
227
+ : node
218
228
 
219
229
  const call = new cs.TokenNodeApplyFunction(
220
230
  new cs.AccessChain([
@@ -223,14 +233,22 @@ export const generateDataclassFileForRoutes = (
223
233
  ]),
224
234
  [new cs.Literal(path), requestOptions],
225
235
  new cs.TypeArgumentsNode([
226
- new cs.TypeNode(new cs.TokenNode(response.className)),
236
+ new cs.TypeNode(
237
+ response
238
+ ? new cs.TokenNode(response.className)
239
+ : cs.TokenNode.TYPE_OBJECT
240
+ ),
227
241
  ])
228
242
  )
229
243
 
230
244
  const result = new cs.AccessChain([
231
- wrapAwait(call),
232
- new cs.TokenNode("Data"),
233
- new cs.TokenNode(pascalCase(return_path)),
245
+ wrapAwait(call, !is_void),
246
+ ...(is_void
247
+ ? []
248
+ : [
249
+ new cs.TokenNode("Data"),
250
+ new cs.TokenNode(pascalCase(return_path)),
251
+ ]),
234
252
  ])
235
253
 
236
254
  const methodSimple = new cs.MethodDeclaration(
@@ -257,7 +275,9 @@ export const generateDataclassFileForRoutes = (
257
275
  requestObj
258
276
  ),
259
277
  // return seam.Post<responseType>(route, requestOptions).Data;
260
- new cs.ReturnStatement(result),
278
+ ...(is_void
279
+ ? [new cs.NodeStatement(result)]
280
+ : [new cs.ReturnStatement(result)]),
261
281
  ]),
262
282
  ]),
263
283
  new cs.VisibilityModifiers([
@@ -266,24 +286,26 @@ export const generateDataclassFileForRoutes = (
266
286
  ])
267
287
  )
268
288
 
289
+ const methodApplyRef = wrapAwait(
290
+ new cs.TokenNodeApplyFunction(methodName, [
291
+ new cs.ApplyConstructorNode(
292
+ new cs.TokenNode(request.className),
293
+ request.parameterDefs.map(
294
+ (pd) => new cs.RawNode(`${pd.name.token}: ${pd.name.token}`)
295
+ )
296
+ ),
297
+ ]),
298
+ !is_void
299
+ )
300
+
269
301
  const methodWithProperties = new cs.MethodDeclaration(
270
302
  wrapTypeTask(responseType),
271
303
  new cs.MethodNode(methodName, request.parameterDefs),
272
304
  new cs.CurlyBlock(
273
305
  [
274
- new cs.ReturnStatement(
275
- wrapAwait(
276
- new cs.TokenNodeApplyFunction(methodName, [
277
- new cs.ApplyConstructorNode(
278
- new cs.TokenNode(request.className),
279
- request.parameterDefs.map(
280
- (pd) =>
281
- new cs.RawNode(`${pd.name.token}: ${pd.name.token}`)
282
- )
283
- ),
284
- ])
285
- )
286
- ),
306
+ is_void
307
+ ? new cs.NodeStatement(methodApplyRef)
308
+ : new cs.ReturnStatement(methodApplyRef),
287
309
  ].map((s) => new cs.StatementBlock([s]))
288
310
  ),
289
311
  new cs.VisibilityModifiers([
@@ -298,7 +320,7 @@ export const generateDataclassFileForRoutes = (
298
320
  classStatements.push(
299
321
  ...[
300
322
  ...request.classDefs,
301
- ...response.classDefs,
323
+ ...(response?.classDefs ?? []),
302
324
  ...getMethod(false),
303
325
  ...getMethod(true),
304
326
  ]
@@ -14,7 +14,7 @@ import gitignoreTemplate from "./templates/gitignore.template.js"
14
14
  import envExampleTemplate from "./templates/env.example.template.js"
15
15
  import testFixtureTemplate from "./templates/test-fixture.template.js"
16
16
  import smokeTestTemplate from "./templates/smoke-test.template.js"
17
- import mapParentToChildrenResources from "lib/openapi/map-parent-to-children-resource.js"
17
+ import mapParentToChildResources from "lib/openapi/map-parent-to-children-resource.js"
18
18
 
19
19
  export const generatePhpSDK = async () => {
20
20
  const openapi: OpenAPISchema = await axios
@@ -65,18 +65,18 @@ export const generatePhpSDK = async () => {
65
65
  }
66
66
  }
67
67
 
68
- const parent_to_children_resources_map = mapParentToChildrenResources(routes)
68
+ const parent_to_child_resources_map = mapParentToChildResources(routes)
69
69
  const clients: Record<string, PhpClient> = {}
70
70
 
71
71
  const processClient = (resource_name: string) => {
72
72
  const child_client_identifiers: PhpClientIdentifier[] = (
73
- parent_to_children_resources_map[resource_name] ?? []
73
+ parent_to_child_resources_map[resource_name] ?? []
74
74
  ).map((child_resource) => ({
75
75
  client_name: pascalCase(`${resource_name} ${child_resource}`),
76
76
  namespace: child_resource,
77
77
  }))
78
78
  const is_parent_client = Object.keys(
79
- parent_to_children_resources_map
79
+ parent_to_child_resources_map
80
80
  ).includes(resource_name)
81
81
  const pascal_resource_name = pascalCase(resource_name)
82
82
 
@@ -186,7 +186,7 @@ export class ClassFile {
186
186
  return_resource_item = return_resource.slice(5, -1)
187
187
  }
188
188
 
189
- const does_method_use_action_attempt_polling =
189
+ const can_method_poll_action_attempt =
190
190
  !is_action_attempt_class &&
191
191
  return_resource === "ActionAttempt" &&
192
192
  !is_return_resource_list
@@ -207,7 +207,7 @@ export class ClassFile {
207
207
  : `${name}: Optional[${type}] = None`
208
208
  )
209
209
  .concat(
210
- does_method_use_action_attempt_polling
210
+ can_method_poll_action_attempt
211
211
  ? [
212
212
  "wait_for_action_attempt: Union[bool, Dict[str, float]] = True",
213
213
  ]
@@ -231,7 +231,7 @@ export class ClassFile {
231
231
  ` )`,
232
232
  "",
233
233
 
234
- does_method_use_action_attempt_polling
234
+ can_method_poll_action_attempt
235
235
  ? [
236
236
  " if isinstance(wait_for_action_attempt, dict):",
237
237
  ` updated_action_attempt = self.seam.action_attempts.poll_until_ready(`,
@@ -253,7 +253,7 @@ export class ClassFile {
253
253
  : "",
254
254
  "",
255
255
 
256
- !does_method_use_action_attempt_polling
256
+ !can_method_poll_action_attempt
257
257
  ? is_none_return_type
258
258
  ? ` return None`
259
259
  : is_return_resource_list
@@ -21,7 +21,7 @@ import reportErrorTemplate from "./templates/utils/report_error.py.template.js"
21
21
  import getSentryDsnTemplate from "./templates/utils/get_sentry_dsn.py.template.js"
22
22
  import SeamApiExceptionClassTemplate from "./templates/snippets/seam-api-exception-class.template.js"
23
23
  import { getParameterAndResponseSchema } from "lib/openapi/get-parameter-and-response-schema.js"
24
- import mapParentToChildrenResources from "lib/openapi/map-parent-to-children-resource.js"
24
+ import mapParentToChildResources from "lib/openapi/map-parent-to-children-resource.js"
25
25
  import { deepFlattenOneOfAndAllOfSchema } from "lib/generate-php-sdk/utils/deep-flatten-one-of-and-all-of-schema.js"
26
26
  import endpoints_returning_deprecated_action_attempt from "lib/endpoints-returning-deprecated-action-attempt.js"
27
27
 
@@ -37,11 +37,11 @@ export const generatePythonSDK = async () => {
37
37
  const fs: any = {}
38
38
  const class_map: Record<string, ClassFile> = {}
39
39
  const namespaces: string[][] = []
40
- const parent_to_children_resources_map = mapParentToChildrenResources(routes)
40
+ const parent_to_child_resources_map = mapParentToChildResources(routes)
41
41
 
42
42
  const processClass = (resource_name: string) => {
43
43
  const child_class_identifiers = (
44
- parent_to_children_resources_map[resource_name] ?? []
44
+ parent_to_child_resources_map[resource_name] ?? []
45
45
  ).map((child_resource) => ({
46
46
  class_name: pascalCase(`${resource_name} ${child_resource}`),
47
47
  namespace: child_resource,
@@ -61,7 +61,6 @@ export const generatePythonSDK = async () => {
61
61
  const group_names = [...route.post["x-fern-sdk-group-name"]]
62
62
  const [base_resource] = group_names
63
63
  const namespace = group_names.join("_")
64
- group_names.reverse()
65
64
  const class_name = pascalCase(namespace)
66
65
 
67
66
  if (!class_map[class_name]) {
@@ -14,11 +14,16 @@ import loggerRbTemplate from "./templates/logger.rb.template.js"
14
14
  import clientRbTemplate from "./templates/client.rb.template.js"
15
15
  import gemfileTemplate from "./templates/gemfile.template.js"
16
16
  import seamapiGemspecTemplate from "./templates/seamapi.gemspec.template.js"
17
+ import rspecTemplate from "./templates/.rspec.template.js"
18
+ import rubyVersionTemplate from "./templates/.ruby-version.template.js"
19
+ import supportHelpersTemplate from "./templates/support-helpers.rb.template.js"
20
+ import specHelperTemplate from "./templates/spec_helper.rb.template.js"
17
21
  import base_resourceRbTemplate from "./templates/base_resource.rb.template.js"
18
22
  import resource_errorRbTemplate from "./templates/resource_error.rb.template.js"
19
23
  import resource_warningRbTemplate from "./templates/resource_warning.rb.template.js"
20
24
  import resource_errors_supportRbTemplate from "./templates/resource_errors_support.rb.template.js"
21
25
  import resource_warnings_supportRbTemplate from "./templates/resource_warnings_support.rb.template.js"
26
+ import mapParentToChildResources from "lib/openapi/map-parent-to-children-resource.js"
22
27
 
23
28
  export const generateRubySDK = async () => {
24
29
  const openapi: OpenAPISchema = await axios
@@ -33,14 +38,16 @@ export const generateRubySDK = async () => {
33
38
 
34
39
  fs["README.md"] = readmeMdTemplate()
35
40
  fs["Rakefile"] = rakefileTemplate()
36
- fs["spec/spec_helper.rb"] = ""
41
+ fs["spec/spec_helper.rb"] = specHelperTemplate()
42
+ fs["spec/support/helpers.rb"] = supportHelpersTemplate()
37
43
  fs["spec/smoketest.rb"] = ""
38
44
  fs["Gemfile"] = gemfileTemplate()
39
45
  fs["seamapi.gemspec"] = seamapiGemspecTemplate()
46
+ fs[".rspec"] = rspecTemplate()
47
+ fs[".ruby-version"] = rubyVersionTemplate()
40
48
  fs["lib/seam/version.rb"] = versionRbTemplate()
41
49
  fs["lib/seam/request.rb"] = requestRbTemplate()
42
50
  fs["lib/seam/logger.rb"] = loggerRbTemplate()
43
- fs["lib/seam/client.rb"] = clientRbTemplate()
44
51
  fs["lib/seam/clients/base_client.rb"] = base_clientRbTemplate()
45
52
  fs["lib/seam/resources/base_resource.rb"] = base_resourceRbTemplate()
46
53
  fs["lib/seam/resources/resource_error.rb"] = resource_errorRbTemplate()
@@ -85,21 +92,46 @@ export const generateRubySDK = async () => {
85
92
  }
86
93
 
87
94
  const clients: Record<string, RubyClient> = {}
95
+ const parent_to_child_resources_map = mapParentToChildResources(routes)
96
+
97
+ const processClient = (resource_name: string) => {
98
+ const child_class_identifiers = (
99
+ parent_to_child_resources_map[resource_name] ?? []
100
+ ).map((child_resource) => ({
101
+ client_name: pascalCase(`${resource_name} ${child_resource}`),
102
+ namespace: child_resource,
103
+ }))
104
+ const pascal_resource_name = pascalCase(resource_name)
105
+
106
+ clients[pascal_resource_name] = new RubyClient(
107
+ pascal_resource_name,
108
+ resource_name,
109
+ child_class_identifiers
110
+ )
111
+ }
112
+
88
113
  for (const route of routes) {
89
114
  if (!route.post) continue
90
115
  if (!route.post["x-fern-sdk-group-name"]) continue
91
116
  const group_names = [...route.post["x-fern-sdk-group-name"]]
117
+ const [base_resource] = group_names
92
118
  const namespace = group_names.join("_")
93
- group_names.reverse()
94
- const class_name = pascalCase(group_names.join("_"))
95
- if (!clients[class_name]) {
96
- // namespaces.push(route.post["x-fern-sdk-group-name"])
97
- clients[class_name] = new RubyClient(class_name, namespace)
119
+ const client_name = pascalCase(group_names.join("_"))
120
+
121
+ if (!clients[client_name]) processClient(namespace)
122
+
123
+ /*
124
+ special case when we don't have routes for a base resource
125
+ and thus a respective x-fern-sdk-group-name for ex. /noise_sensors
126
+ */
127
+ if (base_resource && !clients[pascalCase(base_resource)]) {
128
+ processClient(base_resource)
98
129
  }
99
- const client = clients[class_name]
130
+
131
+ const client = clients[client_name]
100
132
 
101
133
  if (!client) {
102
- console.warn(`No client for "${class_name}", skipping`)
134
+ console.warn(`No client for "${client_name}", skipping`)
103
135
  continue
104
136
  }
105
137
 
@@ -111,10 +143,7 @@ export const generateRubySDK = async () => {
111
143
  continue
112
144
  }
113
145
 
114
- if (!response_obj_type && !response_arr_type) {
115
- console.warn(`No response object/array ref for "${route.path}", skipping`)
116
- continue
117
- }
146
+ const return_resource = response_obj_type ?? response_arr_type
118
147
 
119
148
  client.addMethod({
120
149
  method_name: route.post["x-fern-sdk-method-name"],
@@ -131,7 +160,7 @@ export const generateRubySDK = async () => {
131
160
  : undefined,
132
161
  })),
133
162
  return_path: route.post["x-fern-sdk-return-value"],
134
- return_resource: pascalCase(response_obj_type ?? response_arr_type),
163
+ return_resource: return_resource ? pascalCase(return_resource) : null,
135
164
  })
136
165
  }
137
166
 
@@ -140,6 +169,10 @@ export const generateRubySDK = async () => {
140
169
  seamapi_rb_requires.push(`seam/clients/${client.snake_name}`)
141
170
  }
142
171
 
172
+ fs["lib/seam/client.rb"] = clientRbTemplate(
173
+ Object.keys(parent_to_child_resources_map)
174
+ )
175
+
143
176
  fs["lib/seamapi.rb"] = [
144
177
  `# frozen_string_literal: true`,
145
178
  "",
@@ -1,3 +1,5 @@
1
+ import endpoints_returning_deprecated_action_attempt from "lib/endpoints-returning-deprecated-action-attempt.js"
2
+
1
3
  export type RubyClientMethodParameter = {
2
4
  name: string
3
5
  required?: boolean | undefined
@@ -8,18 +10,26 @@ export type RubyClientMethod = {
8
10
  method_name: string
9
11
  path: string
10
12
  parameters: RubyClientMethodParameter[]
11
- return_resource: string
13
+ return_resource: string | null
12
14
  return_path: string
13
15
  }
14
16
 
17
+ type ChildClientIdentifier = {
18
+ client_name: string
19
+ namespace: string
20
+ }
21
+
15
22
  export class RubyClient {
16
23
  methods: RubyClientMethod[] = []
24
+ child_client_identifiers: ChildClientIdentifier[]
17
25
 
18
26
  constructor(
19
27
  public pascal_name: string,
20
- public snake_name: string
28
+ public snake_name: string,
29
+ child_client_identifiers: ChildClientIdentifier[]
21
30
  ) {
22
31
  this.methods = []
32
+ this.child_client_identifiers = child_client_identifiers
23
33
  }
24
34
 
25
35
  addMethod(method: RubyClientMethod) {
@@ -43,13 +53,30 @@ export class RubyClient {
43
53
  */
44
54
  serialize() {
45
55
  return [
56
+ `# frozen_string_literal: true`,
57
+ ``,
46
58
  `module Seam`,
47
59
  ` module Clients`,
48
60
  ` class ${this.pascal_name} < BaseClient`,
61
+ ...this.child_client_identifiers.map(({ client_name, namespace }) =>
62
+ [
63
+ `def ${namespace}`,
64
+ ` @${namespace} ||= Seam::Clients::${client_name}.new(self)`,
65
+ `end`,
66
+ ``,
67
+ ]
68
+ .flatMap((s) => ` ${s}`)
69
+ .join("\n")
70
+ ),
49
71
  ...this.methods.map(
50
72
  ({ method_name, path, parameters, return_resource, return_path }) => {
73
+ const is_action_attempt_client = this.pascal_name === "ActionAttempts"
74
+ const can_method_poll_action_attempt =
75
+ !endpoints_returning_deprecated_action_attempt.includes(path) &&
76
+ !is_action_attempt_client &&
77
+ return_resource === "ActionAttempt"
78
+
51
79
  return [
52
- " ",
53
80
  `def ${method_name}(${parameters
54
81
  .sort(
55
82
  (a, b) =>
@@ -58,18 +85,26 @@ export class RubyClient {
58
85
  )
59
86
  .map((p) => `${p.name}${p.required ? "" : ": nil"}`)
60
87
  .join(", ")})`,
61
- ` request_seam_object(`,
88
+ ` ${can_method_poll_action_attempt ? "action_attempt = " : ""}${
89
+ return_resource ? "request_seam_object" : "request_seam"
90
+ }(`,
62
91
  ` :post,`,
63
92
  ` "${path}",`,
64
- ` ${return_resource},`,
65
- ` '${return_path}',`,
93
+ return_resource ? ` Seam::${return_resource},` : [],
94
+ return_path ? ` '${return_path}',` : [],
66
95
  ` body: {${parameters
67
96
  .map((p) => `${p.name}: ${p.name}`)
68
97
  .join(", ")}}.compact`,
69
98
  ` )`,
99
+ ` ${
100
+ can_method_poll_action_attempt
101
+ ? "action_attempt.wait_until_finished\n action_attempt"
102
+ : ""
103
+ }`,
70
104
  `end`,
105
+ ``,
71
106
  ]
72
- .map((s) => ` ${s}`)
107
+ .flatMap((s) => ` ${s}`)
73
108
  .join("\n")
74
109
  }
75
110
  ),
@@ -0,0 +1,3 @@
1
+ export default () => `--format documentation
2
+ --color
3
+ --require spec_helper`
@@ -0,0 +1 @@
1
+ export default () => `3.0.4`