@seamapi/nextlove-sdk-generator 1.9.0 → 1.10.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 (34) hide show
  1. package/lib/generate-python-sdk/generate-python-sdk.js +7 -0
  2. package/lib/generate-python-sdk/generate-python-sdk.js.map +1 -1
  3. package/lib/generate-python-sdk/templates/__init__.py.template.js +8 -2
  4. package/lib/generate-python-sdk/templates/__init__.py.template.js.map +1 -1
  5. package/lib/generate-python-sdk/templates/auth.py.template.d.ts +2 -0
  6. package/lib/generate-python-sdk/templates/auth.py.template.js +103 -0
  7. package/lib/generate-python-sdk/templates/auth.py.template.js.map +1 -0
  8. package/lib/generate-python-sdk/templates/conftest.py.template.js +8 -17
  9. package/lib/generate-python-sdk/templates/conftest.py.template.js.map +1 -1
  10. package/lib/generate-python-sdk/templates/parse_options.py.template.d.ts +2 -0
  11. package/lib/generate-python-sdk/templates/parse_options.py.template.js +91 -0
  12. package/lib/generate-python-sdk/templates/parse_options.py.template.js.map +1 -0
  13. package/lib/generate-python-sdk/templates/routes.py.template.js +0 -3
  14. package/lib/generate-python-sdk/templates/routes.py.template.js.map +1 -1
  15. package/lib/generate-python-sdk/templates/seam.py.template.js +55 -36
  16. package/lib/generate-python-sdk/templates/seam.py.template.js.map +1 -1
  17. package/lib/generate-python-sdk/templates/snippets/abstract-routes.template.js +1 -4
  18. package/lib/generate-python-sdk/templates/snippets/abstract-routes.template.js.map +1 -1
  19. package/lib/generate-python-sdk/templates/snippets/abstract-seam.template.js +34 -9
  20. package/lib/generate-python-sdk/templates/snippets/abstract-seam.template.js.map +1 -1
  21. package/lib/generate-python-sdk/templates/token.py.template.d.ts +2 -0
  22. package/lib/generate-python-sdk/templates/token.py.template.js +49 -0
  23. package/lib/generate-python-sdk/templates/token.py.template.js.map +1 -0
  24. package/package.json +1 -1
  25. package/src/lib/generate-python-sdk/generate-python-sdk.ts +7 -0
  26. package/src/lib/generate-python-sdk/templates/__init__.py.template.ts +8 -2
  27. package/src/lib/generate-python-sdk/templates/auth.py.template.ts +102 -0
  28. package/src/lib/generate-python-sdk/templates/conftest.py.template.ts +8 -17
  29. package/src/lib/generate-python-sdk/templates/parse_options.py.template.ts +90 -0
  30. package/src/lib/generate-python-sdk/templates/routes.py.template.ts +0 -3
  31. package/src/lib/generate-python-sdk/templates/seam.py.template.ts +55 -36
  32. package/src/lib/generate-python-sdk/templates/snippets/abstract-routes.template.ts +1 -4
  33. package/src/lib/generate-python-sdk/templates/snippets/abstract-seam.template.ts +34 -9
  34. package/src/lib/generate-python-sdk/templates/token.py.template.ts +48 -0
@@ -16,6 +16,9 @@ import readmeMdTemplate from "./templates/readme.md.template.js";
16
16
  import initTemplate from "./templates/__init__.py.template.js";
17
17
  import gitignoreTemplate from "./templates/.gitignore.template.js";
18
18
  import SeamApiExceptionClassTemplate from "./templates/snippets/seam-api-exception-class.template.js";
19
+ import authPyTemplate from "./templates/auth.py.template.js";
20
+ import parseOptionsPyTemplate from "./templates/parse_options.py.template.js";
21
+ import tokenPyTemplate from "./templates/token.py.template.js";
19
22
  import { getParameterAndResponseSchema } from "../../lib/openapi/get-parameter-and-response-schema.js";
20
23
  import mapParentToChildResources from "../../lib/openapi/map-parent-to-children-resource.js";
21
24
  import { deepFlattenOneOfAndAllOfSchema } from "../../lib/generate-php-sdk/utils/deep-flatten-one-of-and-all-of-schema.js";
@@ -105,6 +108,7 @@ export const generatePythonSDK = async (options = {}) => {
105
108
  }
106
109
  fs[`seam/types.py`] = [
107
110
  `from typing import Any, Dict, List, Optional, Union`,
111
+ `from typing_extensions import Self`,
108
112
  `import abc`,
109
113
  `from dataclasses import dataclass`,
110
114
  `from seam.utils.deep_attr_dict import DeepAttrDict`,
@@ -138,6 +142,9 @@ export const generatePythonSDK = async (options = {}) => {
138
142
  fs["seam/__init__.py"] = initTemplate();
139
143
  fs["seam/routes.py"] = routesPyTemplate(top_level_namespaces);
140
144
  fs["seam/seam.py"] = seamPyTemplate();
145
+ fs["seam/auth.py"] = authPyTemplate();
146
+ fs["seam/token.py"] = tokenPyTemplate();
147
+ fs["seam/parse_options.py"] = parseOptionsPyTemplate();
141
148
  fs["seam/utils/deep_attr_dict.py"] = deepAttrDictPyTemplate();
142
149
  fs["seam/utils/action_attempt_errors.py"] = actionAttemptsErrorsPyTemplate();
143
150
  fs["tests/conftest.py"] = conftestPyTemplate();
@@ -1 +1 @@
1
- {"version":3,"file":"generate-python-sdk.js","sourceRoot":"","sources":["../../src/lib/generate-python-sdk/generate-python-sdk.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate-python-sdk.js","sourceRoot":"","sources":["../../src/lib/generate-python-sdk/generate-python-sdk.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,13 @@
1
1
  export default () => `# flake8: noqa
2
2
  # type: ignore
3
3
 
4
- from seam.seam import Seam
5
- from seam.seam import SeamApiException
4
+ from seam.seam import Seam, SeamApiException
5
+ from seam.parse_options import SeamHttpInvalidOptionsError
6
+ from seam.auth import SeamHttpInvalidToken
7
+ from seam.utils.action_attempt_errors import (
8
+ SeamActionAttemptError,
9
+ SeamActionAttemptFailedError,
10
+ SeamActionAttemptTimeoutError,
11
+ )
6
12
  `;
7
13
  //# sourceMappingURL=__init__.py.template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"__init__.py.template.js","sourceRoot":"","sources":["../../../src/lib/generate-python-sdk/templates/__init__.py.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;CAKpB,CAAA"}
1
+ {"version":3,"file":"__init__.py.template.js","sourceRoot":"","sources":["../../../src/lib/generate-python-sdk/templates/__init__.py.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;;;;;;;CAWpB,CAAA"}
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,103 @@
1
+ export default () => `from typing import Optional
2
+ from seam.parse_options import (
3
+ SeamHttpInvalidOptionsError,
4
+ is_seam_http_options_with_api_key,
5
+ is_seam_http_options_with_personal_access_token,
6
+ )
7
+ from seam.token import (
8
+ is_jwt,
9
+ is_access_token,
10
+ is_client_session_token,
11
+ is_publishable_key,
12
+ is_seam_token,
13
+ token_prefix,
14
+ access_token_prefix,
15
+ )
16
+
17
+
18
+ class SeamHttpInvalidTokenError(Exception):
19
+ def __init__(self, message):
20
+ super().__init__(f"SeamHttp received an invalid token: {message}")
21
+
22
+
23
+ def get_auth_headers(
24
+ api_key: Optional[str] = None,
25
+ personal_access_token: Optional[str] = None,
26
+ workspace_id: Optional[str] = None,
27
+ ):
28
+ if is_seam_http_options_with_api_key(
29
+ api_key=api_key,
30
+ personal_access_token=personal_access_token,
31
+ ):
32
+ return get_auth_headers_for_api_key(api_key)
33
+
34
+ if is_seam_http_options_with_personal_access_token(
35
+ personal_access_token=personal_access_token,
36
+ api_key=api_key,
37
+ workspace_id=workspace_id,
38
+ ):
39
+ return get_auth_headers_for_personal_access_token(
40
+ personal_access_token, workspace_id
41
+ )
42
+
43
+ raise SeamHttpInvalidOptionsError(
44
+ "Must specify an api_key or personal_access_token. "
45
+ "Attempted reading configuration from the environment, "
46
+ "but the environment variable SEAM_API_KEY is not set."
47
+ )
48
+
49
+
50
+ def get_auth_headers_for_api_key(api_key: str) -> dict:
51
+ if is_client_session_token(api_key):
52
+ raise SeamHttpInvalidTokenError(
53
+ "A Client Session Token cannot be used as an api_key"
54
+ )
55
+
56
+ if is_jwt(api_key):
57
+ raise SeamHttpInvalidTokenError("A JWT cannot be used as an api_key")
58
+
59
+ if is_access_token(api_key):
60
+ raise SeamHttpInvalidTokenError("An Access Token cannot be used as an api_key")
61
+
62
+ if is_publishable_key(api_key):
63
+ raise SeamHttpInvalidTokenError(
64
+ "A Publishable Key cannot be used as an api_key"
65
+ )
66
+
67
+ if not is_seam_token(api_key):
68
+ raise SeamHttpInvalidTokenError(
69
+ f"Unknown or invalid api_key format, expected token to start with {token_prefix}"
70
+ )
71
+
72
+ return {"authorization": f"Bearer {api_key}"}
73
+
74
+
75
+ def get_auth_headers_for_personal_access_token(
76
+ personal_access_token: str, workspace_id: str
77
+ ) -> dict:
78
+ if is_jwt(personal_access_token):
79
+ raise SeamHttpInvalidTokenError(
80
+ "A JWT cannot be used as a personal_access_token"
81
+ )
82
+
83
+ if is_client_session_token(personal_access_token):
84
+ raise SeamHttpInvalidTokenError(
85
+ "A Client Session Token cannot be used as a personal_access_token"
86
+ )
87
+
88
+ if is_publishable_key(personal_access_token):
89
+ raise SeamHttpInvalidTokenError(
90
+ "A Publishable Key cannot be used as a personal_access_token"
91
+ )
92
+
93
+ if not is_access_token(personal_access_token):
94
+ raise SeamHttpInvalidTokenError(
95
+ f"Unknown or invalid personal_access_token format, expected token to start with {access_token_prefix}"
96
+ )
97
+
98
+ return {
99
+ "authorization": f"Bearer {personal_access_token}",
100
+ "seam-workspace": workspace_id,
101
+ }
102
+ `;
103
+ //# sourceMappingURL=auth.py.template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.py.template.js","sourceRoot":"","sources":["../../../src/lib/generate-python-sdk/templates/auth.py.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqGpB,CAAA"}
@@ -1,24 +1,15 @@
1
- export default () => `import random
2
- import string
3
- import pytest
1
+ export default () => `import pytest
4
2
  from seam import Seam
5
- from dotenv import load_dotenv
6
3
  from typing import Any
7
- from dataclasses import dataclass
8
-
9
-
10
- @pytest.fixture(autouse=True)
11
- def dotenv_fixture():
12
- load_dotenv()
4
+ import random
5
+ import string
13
6
 
14
- # TODO this should use scope="session", but there's some issue, this would
15
- # dramatically reduce test time to switch
16
7
  @pytest.fixture(scope="function")
17
- def seam_backend():
18
- random_string = ''.join(random.choices(string.ascii_uppercase + string.digits, k=10))
19
- yield SeamBackend(
20
- url=f"https://{random_string}.fakeseamconnect.seam.vc",
21
- sandbox_api_key="seam_apikey1_token",
8
+ def seam():
9
+ r = "".join(random.choices(string.ascii_uppercase + string.digits, k=10))
10
+ seam = Seam(
11
+ endpoint=f"https://{r}.fakeseamconnect.seam.vc", api_key="seam_apikey1_token"
22
12
  )
13
+ yield seam
23
14
  `;
24
15
  //# sourceMappingURL=conftest.py.template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"conftest.py.template.js","sourceRoot":"","sources":["../../../src/lib/generate-python-sdk/templates/conftest.py.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;CAsBpB,CAAA"}
1
+ {"version":3,"file":"conftest.py.template.js","sourceRoot":"","sources":["../../../src/lib/generate-python-sdk/templates/conftest.py.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;;;;;;;;;CAapB,CAAA"}
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,91 @@
1
+ export default () => `import os
2
+ from typing import Optional
3
+
4
+ from seam.auth import get_auth_headers
5
+
6
+ DEFAULT_ENDPOINT = "https://connect.getseam.com"
7
+
8
+
9
+ def parse_options(
10
+ api_key: Optional[str] = None,
11
+ personal_access_token: Optional[str] = None,
12
+ workspace_id: Optional[str] = None,
13
+ endpoint: Optional[str] = None,
14
+ ):
15
+ if personal_access_token is None:
16
+ api_key = api_key or os.getenv("SEAM_API_KEY")
17
+
18
+ auth_headers = get_auth_headers(
19
+ api_key=api_key,
20
+ personal_access_token=personal_access_token,
21
+ workspace_id=workspace_id,
22
+ )
23
+ endpoint = endpoint or get_endpoint_from_env() or DEFAULT_ENDPOINT
24
+
25
+ return auth_headers, endpoint
26
+
27
+
28
+ def get_endpoint_from_env():
29
+ seam_api_url = os.getenv("SEAM_API_URL")
30
+ seam_endpoint = os.getenv("SEAM_ENDPOINT")
31
+
32
+ if seam_api_url is not None:
33
+ print(
34
+ "\\033[93m"
35
+ "Using the SEAM_API_URL environment variable is deprecated. "
36
+ "Support will be removed in a later major version. Use SEAM_ENDPOINT instead."
37
+ "\\033[0m"
38
+ )
39
+
40
+ if seam_api_url is not None and seam_endpoint is not None:
41
+ print(
42
+ "\\033[93m"
43
+ "Detected both the SEAM_API_URL and SEAM_ENDPOINT environment variables. "
44
+ "Using SEAM_ENDPOINT."
45
+ "\\033[0m"
46
+ )
47
+
48
+ return seam_endpoint or seam_api_url
49
+
50
+
51
+ class SeamHttpInvalidOptionsError(Exception):
52
+ def __init__(self, message):
53
+ super().__init__(f"SeamHttp received invalid options: {message}")
54
+
55
+
56
+ def is_seam_http_options_with_api_key(
57
+ api_key: Optional[str] = None,
58
+ personal_access_token: Optional[str] = None,
59
+ ) -> bool:
60
+ if api_key is None:
61
+ return False
62
+
63
+ if personal_access_token is not None:
64
+ raise SeamHttpInvalidOptionsError(
65
+ "The personal_access_token option cannot be used with the api_key option"
66
+ )
67
+
68
+ return True
69
+
70
+
71
+ def is_seam_http_options_with_personal_access_token(
72
+ personal_access_token: Optional[str] = None,
73
+ api_key: Optional[str] = None,
74
+ workspace_id: Optional[str] = None,
75
+ ) -> bool:
76
+ if personal_access_token is None:
77
+ return False
78
+
79
+ if api_key is not None:
80
+ raise SeamHttpInvalidOptionsError(
81
+ "The api_key option cannot be used with the personal_access_token option"
82
+ )
83
+
84
+ if workspace_id is None:
85
+ raise SeamHttpInvalidOptionsError(
86
+ "Must pass a workspace_id when using a personal_access_token"
87
+ )
88
+
89
+ return True
90
+ `;
91
+ //# sourceMappingURL=parse_options.py.template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse_options.py.template.js","sourceRoot":"","sources":["../../../src/lib/generate-python-sdk/templates/parse_options.py.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyFpB,CAAA"}
@@ -6,8 +6,5 @@ export default (namespaces) => [
6
6
  `class Routes(AbstractRoutes):`,
7
7
  ` def __init__(self):`,
8
8
  ...namespaces.map((ns) => ` self.${ns} = ${pascalCase(ns)}(seam=self)`),
9
- ``,
10
- ` def make_request(self, method: str, path: str, **kwargs):`,
11
- ` raise NotImplementedError()`,
12
9
  ].join("\n");
13
10
  //# sourceMappingURL=routes.py.template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"routes.py.template.js","sourceRoot":"","sources":["../../../src/lib/generate-python-sdk/templates/routes.py.template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,eAAe,CAAC,UAAoB,EAAE,EAAE,CACtC;IACE,mCAAmC;IACnC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,EAAE,WAAW,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;IACjE,EAAE;IACF,+BAA+B;IAC/B,uBAAuB;IACvB,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,YAAY,EAAE,MAAM,UAAU,CAAC,EAAE,CAAC,aAAa,CAAC;IAC1E,EAAE;IACF,6DAA6D;IAC7D,iCAAiC;CAClC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA"}
1
+ {"version":3,"file":"routes.py.template.js","sourceRoot":"","sources":["../../../src/lib/generate-python-sdk/templates/routes.py.template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,eAAe,CAAC,UAAoB,EAAE,EAAE,CACtC;IACE,mCAAmC;IACnC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,EAAE,WAAW,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;IACjE,EAAE;IACF,+BAA+B;IAC/B,uBAAuB;IACvB,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,YAAY,EAAE,MAAM,UAAU,CAAC,EAAE,CAAC,aAAa,CAAC;CAC3E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA"}
@@ -1,9 +1,10 @@
1
- export default () => `import os
1
+ export default () => `import requests
2
+ from importlib.metadata import version
3
+ from typing import Optional, Union, Dict
4
+ from typing_extensions import Self
2
5
 
6
+ from seam.parse_options import parse_options
3
7
  from .routes import Routes
4
- import requests
5
- from importlib.metadata import version
6
- from typing import Optional, Union, Dict, cast
7
8
  from .types import AbstractSeam, SeamApiException
8
9
 
9
10
 
@@ -12,54 +13,44 @@ class Seam(AbstractSeam):
12
13
  Initial Seam class used to interact with Seam API
13
14
  """
14
15
 
15
- api_key: str
16
- api_url: str = "https://connect.getseam.com"
17
16
  lts_version: str = '1.0.0'
18
17
 
19
18
  def __init__(
20
19
  self,
21
20
  api_key: Optional[str] = None,
22
21
  *,
22
+ personal_access_token: Optional[str] = None,
23
23
  workspace_id: Optional[str] = None,
24
- api_url: Optional[str] = None,
24
+ endpoint: Optional[str] = None,
25
25
  wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
26
26
  ):
27
27
  """
28
28
  Parameters
29
29
  ----------
30
30
  api_key : str, optional
31
- API key
31
+ API key.
32
+ personal_access_token : str, optional
33
+ Personal access token.
32
34
  workspace_id : str, optional
33
- Workspace id
34
- api_url : str, optional
35
- API url
35
+ Workspace id.
36
+ endpoint : str, optional
37
+ The API endpoint to which the request should be sent.
38
+ wait_for_action_attempt : bool or dict, optional
39
+ Controls whether to wait for an action attempt to complete, either as a boolean or as a dictionary specifying \`timeout\` and \`poll_interval\`. Defaults to \`False\`.
36
40
  """
41
+
37
42
  Routes.__init__(self)
38
43
 
39
- if api_key is None:
40
- api_key = os.environ.get("SEAM_API_KEY", None)
41
- if api_key is None:
42
- raise Exception(
43
- "SEAM_API_KEY not found in environment, and api_key not provided"
44
- )
45
- if workspace_id is None:
46
- workspace_id = os.environ.get("SEAM_WORKSPACE_ID", None)
47
- self.api_key = api_key
48
- self.workspace_id = workspace_id
49
44
  self.lts_version = Seam.lts_version
50
45
  self.wait_for_action_attempt = wait_for_action_attempt
51
-
52
- if os.environ.get("SEAM_API_URL", None) is not None:
53
- print(
54
- '\\n'
55
- '\\033[93m'
56
- 'Using the SEAM_API_URL environment variable is deprecated. '
57
- 'Support will be removed in a later major version. Use SEAM_ENDPOINT instead.'
58
- '\\033[0m'
59
- )
60
- api_url = os.environ.get("SEAM_API_URL", None) or os.environ.get("SEAM_ENDPOINT", None) or api_url
61
- if api_url is not None:
62
- self.api_url = cast(str, api_url)
46
+ auth_headers, endpoint = parse_options(
47
+ api_key=api_key,
48
+ personal_access_token=personal_access_token,
49
+ workspace_id=workspace_id,
50
+ endpoint=endpoint,
51
+ )
52
+ self.__auth_headers = auth_headers
53
+ self.__endpoint = endpoint
63
54
 
64
55
  def make_request(self, method: str, path: str, **kwargs):
65
56
  """
@@ -75,12 +66,12 @@ class Seam(AbstractSeam):
75
66
  Keyword arguments passed to requests.request
76
67
  """
77
68
 
78
- url = self.api_url + path
69
+ url = self.__endpoint + path
79
70
  sdk_version = version("seam")
80
71
  headers = {
81
- "Authorization": "Bearer " + self.api_key,
72
+ **self.__auth_headers,
82
73
  "Content-Type": "application/json",
83
- "User-Agent": "Python SDK v" + sdk_version + " (https://github.com/seamapi/python)",
74
+ "User-Agent": "Python SDK v" + sdk_version + " (https://github.com/seamapi/python-next)",
84
75
  "seam-sdk-name": "seamapi/python",
85
76
  "seam-sdk-version": sdk_version,
86
77
  "seam-lts-version": self.lts_version,
@@ -96,5 +87,33 @@ class Seam(AbstractSeam):
96
87
  return response.json()
97
88
 
98
89
  return response.text
90
+
91
+ @classmethod
92
+ def from_api_key(
93
+ cls,
94
+ api_key: str,
95
+ *,
96
+ endpoint: Optional[str] = None,
97
+ wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
98
+ ) -> Self:
99
+ return cls(
100
+ api_key, endpoint=endpoint, wait_for_action_attempt=wait_for_action_attempt
101
+ )
102
+
103
+ @classmethod
104
+ def from_personal_access_token(
105
+ cls,
106
+ personal_access_token: str,
107
+ workspace_id: str,
108
+ *,
109
+ endpoint: Optional[str] = None,
110
+ wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
111
+ ) -> Self:
112
+ return cls(
113
+ personal_access_token=personal_access_token,
114
+ workspace_id=workspace_id,
115
+ endpoint=endpoint,
116
+ wait_for_action_attempt=wait_for_action_attempt,
117
+ )
99
118
  `;
100
119
  //# sourceMappingURL=seam.py.template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"seam.py.template.js","sourceRoot":"","sources":["../../../src/lib/generate-python-sdk/templates/seam.py.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkGpB,CAAA"}
1
+ {"version":3,"file":"seam.py.template.js","sourceRoot":"","sources":["../../../src/lib/generate-python-sdk/templates/seam.py.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqHpB,CAAA"}
@@ -2,8 +2,5 @@ import { pascalCase } from "change-case";
2
2
  export default (namespaces) => `@dataclass
3
3
  class AbstractRoutes(abc.ABC):
4
4
  ${namespaces.map((ns) => ` ${ns}: Abstract${pascalCase(ns)}`).join("\n")}
5
-
6
- @abc.abstractmethod
7
- def make_request(self, method: str, path: str, **kwargs) -> Any:
8
- raise NotImplementedError`;
5
+ `;
9
6
  //# sourceMappingURL=abstract-routes.template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"abstract-routes.template.js","sourceRoot":"","sources":["../../../../src/lib/generate-python-sdk/templates/snippets/abstract-routes.template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,eAAe,CAAC,UAAoB,EAAE,EAAE,CAAC;;EAEvC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,aAAa,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;;8BAI3C,CAAA"}
1
+ {"version":3,"file":"abstract-routes.template.js","sourceRoot":"","sources":["../../../../src/lib/generate-python-sdk/templates/snippets/abstract-routes.template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,eAAe,CAAC,UAAoB,EAAE,EAAE,CAAC;;EAEvC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,aAAa,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;CACxE,CAAA"}
@@ -1,19 +1,44 @@
1
- export default () => `@dataclass
2
- class AbstractSeam(AbstractRoutes):
3
- api_key: str
4
- workspace_id: str
5
- api_url: str
1
+ export default () => `class AbstractSeam(AbstractRoutes):
6
2
  lts_version: str
7
- wait_for_action_attempt: bool
8
3
 
9
4
  @abc.abstractmethod
10
5
  def __init__(
11
6
  self,
12
7
  api_key: Optional[str] = None,
13
8
  *,
9
+ personal_access_token: Optional[str] = None,
14
10
  workspace_id: Optional[str] = None,
15
- api_url: Optional[str] = None,
16
- wait_for_action_attempt: Optional[bool] = False,
11
+ endpoint: Optional[str] = None,
12
+ wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
17
13
  ):
18
- raise NotImplementedError`;
14
+ self.wait_for_action_attempt = wait_for_action_attempt
15
+ self.lts_version = AbstractSeam.lts_version
16
+
17
+ @abc.abstractmethod
18
+ def make_request(self, method: str, path: str, **kwargs) -> Any:
19
+ raise NotImplementedError
20
+
21
+ @classmethod
22
+ @abc.abstractmethod
23
+ def from_api_key(
24
+ cls,
25
+ api_key: str,
26
+ *,
27
+ endpoint: Optional[str] = None,
28
+ wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
29
+ ) -> Self:
30
+ raise NotImplementedError
31
+
32
+ @classmethod
33
+ @abc.abstractmethod
34
+ def from_personal_access_token(
35
+ cls,
36
+ personal_access_token: str,
37
+ workspace_id: str,
38
+ *,
39
+ endpoint: Optional[str] = None,
40
+ wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
41
+ ) -> Self:
42
+ raise NotImplementedError
43
+ `;
19
44
  //# sourceMappingURL=abstract-seam.template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"abstract-seam.template.js","sourceRoot":"","sources":["../../../../src/lib/generate-python-sdk/templates/snippets/abstract-seam.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;;;;;;;;;;;;;kCAiBa,CAAA"}
1
+ {"version":3,"file":"abstract-seam.template.js","sourceRoot":"","sources":["../../../../src/lib/generate-python-sdk/templates/snippets/abstract-seam.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CpB,CAAA"}
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,49 @@
1
+ export default () => `token_prefix = "seam_"
2
+
3
+ access_token_prefix = "seam_at"
4
+
5
+ jwt_prefix = "ey"
6
+
7
+ client_session_token_prefix = "seam_cst"
8
+
9
+ publishable_key_token_prefix = "seam_pk"
10
+
11
+
12
+ def is_access_token(token: str) -> bool:
13
+ return token.startswith(access_token_prefix)
14
+
15
+
16
+ def is_jwt(token: str) -> bool:
17
+ return token.startswith(jwt_prefix)
18
+
19
+
20
+ def is_seam_token(token: str) -> bool:
21
+ return token.startswith(token_prefix)
22
+
23
+
24
+ def is_api_key(token: str) -> bool:
25
+ return (
26
+ not is_client_session_token(token)
27
+ and not is_jwt(token)
28
+ and not is_access_token(token)
29
+ and not is_publishable_key(token)
30
+ and is_seam_token(token)
31
+ )
32
+
33
+
34
+ def is_client_session_token(token: str) -> bool:
35
+ return token.startswith(client_session_token_prefix)
36
+
37
+
38
+ def is_publishable_key(token: str) -> bool:
39
+ return token.startswith(publishable_key_token_prefix)
40
+
41
+
42
+ def is_console_session_token(token: str) -> bool:
43
+ return is_jwt(token)
44
+
45
+
46
+ def is_personal_access_token(token: str) -> bool:
47
+ return is_access_token(token)
48
+ `;
49
+ //# sourceMappingURL=token.py.template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.py.template.js","sourceRoot":"","sources":["../../../src/lib/generate-python-sdk/templates/token.py.template.ts"],"names":[],"mappings":"AAAA,eAAe,GAAG,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CpB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seamapi/nextlove-sdk-generator",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "Utilities for building NextLove SDK Generators",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -17,6 +17,9 @@ import readmeMdTemplate from "./templates/readme.md.template.js"
17
17
  import initTemplate from "./templates/__init__.py.template.js"
18
18
  import gitignoreTemplate from "./templates/.gitignore.template.js"
19
19
  import SeamApiExceptionClassTemplate from "./templates/snippets/seam-api-exception-class.template.js"
20
+ import authPyTemplate from "./templates/auth.py.template.js"
21
+ import parseOptionsPyTemplate from "./templates/parse_options.py.template.js"
22
+ import tokenPyTemplate from "./templates/token.py.template.js"
20
23
  import { getParameterAndResponseSchema } from "lib/openapi/get-parameter-and-response-schema.js"
21
24
  import mapParentToChildResources from "lib/openapi/map-parent-to-children-resource.js"
22
25
  import { deepFlattenOneOfAndAllOfSchema } from "lib/generate-php-sdk/utils/deep-flatten-one-of-and-all-of-schema.js"
@@ -137,6 +140,7 @@ export const generatePythonSDK = async (options: SdkGeneratorOptions = {}) => {
137
140
 
138
141
  fs[`seam/types.py`] = [
139
142
  `from typing import Any, Dict, List, Optional, Union`,
143
+ `from typing_extensions import Self`,
140
144
  `import abc`,
141
145
  `from dataclasses import dataclass`,
142
146
  `from seam.utils.deep_attr_dict import DeepAttrDict`,
@@ -182,6 +186,9 @@ export const generatePythonSDK = async (options: SdkGeneratorOptions = {}) => {
182
186
  fs["seam/__init__.py"] = initTemplate()
183
187
  fs["seam/routes.py"] = routesPyTemplate(top_level_namespaces)
184
188
  fs["seam/seam.py"] = seamPyTemplate()
189
+ fs["seam/auth.py"] = authPyTemplate()
190
+ fs["seam/token.py"] = tokenPyTemplate()
191
+ fs["seam/parse_options.py"] = parseOptionsPyTemplate()
185
192
  fs["seam/utils/deep_attr_dict.py"] = deepAttrDictPyTemplate()
186
193
  fs["seam/utils/action_attempt_errors.py"] = actionAttemptsErrorsPyTemplate()
187
194
 
@@ -1,6 +1,12 @@
1
1
  export default () => `# flake8: noqa
2
2
  # type: ignore
3
3
 
4
- from seam.seam import Seam
5
- from seam.seam import SeamApiException
4
+ from seam.seam import Seam, SeamApiException
5
+ from seam.parse_options import SeamHttpInvalidOptionsError
6
+ from seam.auth import SeamHttpInvalidToken
7
+ from seam.utils.action_attempt_errors import (
8
+ SeamActionAttemptError,
9
+ SeamActionAttemptFailedError,
10
+ SeamActionAttemptTimeoutError,
11
+ )
6
12
  `
@@ -0,0 +1,102 @@
1
+ export default () => `from typing import Optional
2
+ from seam.parse_options import (
3
+ SeamHttpInvalidOptionsError,
4
+ is_seam_http_options_with_api_key,
5
+ is_seam_http_options_with_personal_access_token,
6
+ )
7
+ from seam.token import (
8
+ is_jwt,
9
+ is_access_token,
10
+ is_client_session_token,
11
+ is_publishable_key,
12
+ is_seam_token,
13
+ token_prefix,
14
+ access_token_prefix,
15
+ )
16
+
17
+
18
+ class SeamHttpInvalidTokenError(Exception):
19
+ def __init__(self, message):
20
+ super().__init__(f"SeamHttp received an invalid token: {message}")
21
+
22
+
23
+ def get_auth_headers(
24
+ api_key: Optional[str] = None,
25
+ personal_access_token: Optional[str] = None,
26
+ workspace_id: Optional[str] = None,
27
+ ):
28
+ if is_seam_http_options_with_api_key(
29
+ api_key=api_key,
30
+ personal_access_token=personal_access_token,
31
+ ):
32
+ return get_auth_headers_for_api_key(api_key)
33
+
34
+ if is_seam_http_options_with_personal_access_token(
35
+ personal_access_token=personal_access_token,
36
+ api_key=api_key,
37
+ workspace_id=workspace_id,
38
+ ):
39
+ return get_auth_headers_for_personal_access_token(
40
+ personal_access_token, workspace_id
41
+ )
42
+
43
+ raise SeamHttpInvalidOptionsError(
44
+ "Must specify an api_key or personal_access_token. "
45
+ "Attempted reading configuration from the environment, "
46
+ "but the environment variable SEAM_API_KEY is not set."
47
+ )
48
+
49
+
50
+ def get_auth_headers_for_api_key(api_key: str) -> dict:
51
+ if is_client_session_token(api_key):
52
+ raise SeamHttpInvalidTokenError(
53
+ "A Client Session Token cannot be used as an api_key"
54
+ )
55
+
56
+ if is_jwt(api_key):
57
+ raise SeamHttpInvalidTokenError("A JWT cannot be used as an api_key")
58
+
59
+ if is_access_token(api_key):
60
+ raise SeamHttpInvalidTokenError("An Access Token cannot be used as an api_key")
61
+
62
+ if is_publishable_key(api_key):
63
+ raise SeamHttpInvalidTokenError(
64
+ "A Publishable Key cannot be used as an api_key"
65
+ )
66
+
67
+ if not is_seam_token(api_key):
68
+ raise SeamHttpInvalidTokenError(
69
+ f"Unknown or invalid api_key format, expected token to start with {token_prefix}"
70
+ )
71
+
72
+ return {"authorization": f"Bearer {api_key}"}
73
+
74
+
75
+ def get_auth_headers_for_personal_access_token(
76
+ personal_access_token: str, workspace_id: str
77
+ ) -> dict:
78
+ if is_jwt(personal_access_token):
79
+ raise SeamHttpInvalidTokenError(
80
+ "A JWT cannot be used as a personal_access_token"
81
+ )
82
+
83
+ if is_client_session_token(personal_access_token):
84
+ raise SeamHttpInvalidTokenError(
85
+ "A Client Session Token cannot be used as a personal_access_token"
86
+ )
87
+
88
+ if is_publishable_key(personal_access_token):
89
+ raise SeamHttpInvalidTokenError(
90
+ "A Publishable Key cannot be used as a personal_access_token"
91
+ )
92
+
93
+ if not is_access_token(personal_access_token):
94
+ raise SeamHttpInvalidTokenError(
95
+ f"Unknown or invalid personal_access_token format, expected token to start with {access_token_prefix}"
96
+ )
97
+
98
+ return {
99
+ "authorization": f"Bearer {personal_access_token}",
100
+ "seam-workspace": workspace_id,
101
+ }
102
+ `
@@ -1,23 +1,14 @@
1
- export default () => `import random
2
- import string
3
- import pytest
1
+ export default () => `import pytest
4
2
  from seam import Seam
5
- from dotenv import load_dotenv
6
3
  from typing import Any
7
- from dataclasses import dataclass
8
-
9
-
10
- @pytest.fixture(autouse=True)
11
- def dotenv_fixture():
12
- load_dotenv()
4
+ import random
5
+ import string
13
6
 
14
- # TODO this should use scope="session", but there's some issue, this would
15
- # dramatically reduce test time to switch
16
7
  @pytest.fixture(scope="function")
17
- def seam_backend():
18
- random_string = ''.join(random.choices(string.ascii_uppercase + string.digits, k=10))
19
- yield SeamBackend(
20
- url=f"https://{random_string}.fakeseamconnect.seam.vc",
21
- sandbox_api_key="seam_apikey1_token",
8
+ def seam():
9
+ r = "".join(random.choices(string.ascii_uppercase + string.digits, k=10))
10
+ seam = Seam(
11
+ endpoint=f"https://{r}.fakeseamconnect.seam.vc", api_key="seam_apikey1_token"
22
12
  )
13
+ yield seam
23
14
  `
@@ -0,0 +1,90 @@
1
+ export default () => `import os
2
+ from typing import Optional
3
+
4
+ from seam.auth import get_auth_headers
5
+
6
+ DEFAULT_ENDPOINT = "https://connect.getseam.com"
7
+
8
+
9
+ def parse_options(
10
+ api_key: Optional[str] = None,
11
+ personal_access_token: Optional[str] = None,
12
+ workspace_id: Optional[str] = None,
13
+ endpoint: Optional[str] = None,
14
+ ):
15
+ if personal_access_token is None:
16
+ api_key = api_key or os.getenv("SEAM_API_KEY")
17
+
18
+ auth_headers = get_auth_headers(
19
+ api_key=api_key,
20
+ personal_access_token=personal_access_token,
21
+ workspace_id=workspace_id,
22
+ )
23
+ endpoint = endpoint or get_endpoint_from_env() or DEFAULT_ENDPOINT
24
+
25
+ return auth_headers, endpoint
26
+
27
+
28
+ def get_endpoint_from_env():
29
+ seam_api_url = os.getenv("SEAM_API_URL")
30
+ seam_endpoint = os.getenv("SEAM_ENDPOINT")
31
+
32
+ if seam_api_url is not None:
33
+ print(
34
+ "\\033[93m"
35
+ "Using the SEAM_API_URL environment variable is deprecated. "
36
+ "Support will be removed in a later major version. Use SEAM_ENDPOINT instead."
37
+ "\\033[0m"
38
+ )
39
+
40
+ if seam_api_url is not None and seam_endpoint is not None:
41
+ print(
42
+ "\\033[93m"
43
+ "Detected both the SEAM_API_URL and SEAM_ENDPOINT environment variables. "
44
+ "Using SEAM_ENDPOINT."
45
+ "\\033[0m"
46
+ )
47
+
48
+ return seam_endpoint or seam_api_url
49
+
50
+
51
+ class SeamHttpInvalidOptionsError(Exception):
52
+ def __init__(self, message):
53
+ super().__init__(f"SeamHttp received invalid options: {message}")
54
+
55
+
56
+ def is_seam_http_options_with_api_key(
57
+ api_key: Optional[str] = None,
58
+ personal_access_token: Optional[str] = None,
59
+ ) -> bool:
60
+ if api_key is None:
61
+ return False
62
+
63
+ if personal_access_token is not None:
64
+ raise SeamHttpInvalidOptionsError(
65
+ "The personal_access_token option cannot be used with the api_key option"
66
+ )
67
+
68
+ return True
69
+
70
+
71
+ def is_seam_http_options_with_personal_access_token(
72
+ personal_access_token: Optional[str] = None,
73
+ api_key: Optional[str] = None,
74
+ workspace_id: Optional[str] = None,
75
+ ) -> bool:
76
+ if personal_access_token is None:
77
+ return False
78
+
79
+ if api_key is not None:
80
+ raise SeamHttpInvalidOptionsError(
81
+ "The api_key option cannot be used with the personal_access_token option"
82
+ )
83
+
84
+ if workspace_id is None:
85
+ raise SeamHttpInvalidOptionsError(
86
+ "Must pass a workspace_id when using a personal_access_token"
87
+ )
88
+
89
+ return True
90
+ `
@@ -7,7 +7,4 @@ export default (namespaces: string[]) =>
7
7
  `class Routes(AbstractRoutes):`,
8
8
  ` def __init__(self):`,
9
9
  ...namespaces.map((ns) => ` self.${ns} = ${pascalCase(ns)}(seam=self)`),
10
- ``,
11
- ` def make_request(self, method: str, path: str, **kwargs):`,
12
- ` raise NotImplementedError()`,
13
10
  ].join("\n")
@@ -1,9 +1,10 @@
1
- export default () => `import os
1
+ export default () => `import requests
2
+ from importlib.metadata import version
3
+ from typing import Optional, Union, Dict
4
+ from typing_extensions import Self
2
5
 
6
+ from seam.parse_options import parse_options
3
7
  from .routes import Routes
4
- import requests
5
- from importlib.metadata import version
6
- from typing import Optional, Union, Dict, cast
7
8
  from .types import AbstractSeam, SeamApiException
8
9
 
9
10
 
@@ -12,54 +13,44 @@ class Seam(AbstractSeam):
12
13
  Initial Seam class used to interact with Seam API
13
14
  """
14
15
 
15
- api_key: str
16
- api_url: str = "https://connect.getseam.com"
17
16
  lts_version: str = '1.0.0'
18
17
 
19
18
  def __init__(
20
19
  self,
21
20
  api_key: Optional[str] = None,
22
21
  *,
22
+ personal_access_token: Optional[str] = None,
23
23
  workspace_id: Optional[str] = None,
24
- api_url: Optional[str] = None,
24
+ endpoint: Optional[str] = None,
25
25
  wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
26
26
  ):
27
27
  """
28
28
  Parameters
29
29
  ----------
30
30
  api_key : str, optional
31
- API key
31
+ API key.
32
+ personal_access_token : str, optional
33
+ Personal access token.
32
34
  workspace_id : str, optional
33
- Workspace id
34
- api_url : str, optional
35
- API url
35
+ Workspace id.
36
+ endpoint : str, optional
37
+ The API endpoint to which the request should be sent.
38
+ wait_for_action_attempt : bool or dict, optional
39
+ Controls whether to wait for an action attempt to complete, either as a boolean or as a dictionary specifying \`timeout\` and \`poll_interval\`. Defaults to \`False\`.
36
40
  """
41
+
37
42
  Routes.__init__(self)
38
43
 
39
- if api_key is None:
40
- api_key = os.environ.get("SEAM_API_KEY", None)
41
- if api_key is None:
42
- raise Exception(
43
- "SEAM_API_KEY not found in environment, and api_key not provided"
44
- )
45
- if workspace_id is None:
46
- workspace_id = os.environ.get("SEAM_WORKSPACE_ID", None)
47
- self.api_key = api_key
48
- self.workspace_id = workspace_id
49
44
  self.lts_version = Seam.lts_version
50
45
  self.wait_for_action_attempt = wait_for_action_attempt
51
-
52
- if os.environ.get("SEAM_API_URL", None) is not None:
53
- print(
54
- '\\n'
55
- '\\033[93m'
56
- 'Using the SEAM_API_URL environment variable is deprecated. '
57
- 'Support will be removed in a later major version. Use SEAM_ENDPOINT instead.'
58
- '\\033[0m'
59
- )
60
- api_url = os.environ.get("SEAM_API_URL", None) or os.environ.get("SEAM_ENDPOINT", None) or api_url
61
- if api_url is not None:
62
- self.api_url = cast(str, api_url)
46
+ auth_headers, endpoint = parse_options(
47
+ api_key=api_key,
48
+ personal_access_token=personal_access_token,
49
+ workspace_id=workspace_id,
50
+ endpoint=endpoint,
51
+ )
52
+ self.__auth_headers = auth_headers
53
+ self.__endpoint = endpoint
63
54
 
64
55
  def make_request(self, method: str, path: str, **kwargs):
65
56
  """
@@ -75,12 +66,12 @@ class Seam(AbstractSeam):
75
66
  Keyword arguments passed to requests.request
76
67
  """
77
68
 
78
- url = self.api_url + path
69
+ url = self.__endpoint + path
79
70
  sdk_version = version("seam")
80
71
  headers = {
81
- "Authorization": "Bearer " + self.api_key,
72
+ **self.__auth_headers,
82
73
  "Content-Type": "application/json",
83
- "User-Agent": "Python SDK v" + sdk_version + " (https://github.com/seamapi/python)",
74
+ "User-Agent": "Python SDK v" + sdk_version + " (https://github.com/seamapi/python-next)",
84
75
  "seam-sdk-name": "seamapi/python",
85
76
  "seam-sdk-version": sdk_version,
86
77
  "seam-lts-version": self.lts_version,
@@ -96,4 +87,32 @@ class Seam(AbstractSeam):
96
87
  return response.json()
97
88
 
98
89
  return response.text
90
+
91
+ @classmethod
92
+ def from_api_key(
93
+ cls,
94
+ api_key: str,
95
+ *,
96
+ endpoint: Optional[str] = None,
97
+ wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
98
+ ) -> Self:
99
+ return cls(
100
+ api_key, endpoint=endpoint, wait_for_action_attempt=wait_for_action_attempt
101
+ )
102
+
103
+ @classmethod
104
+ def from_personal_access_token(
105
+ cls,
106
+ personal_access_token: str,
107
+ workspace_id: str,
108
+ *,
109
+ endpoint: Optional[str] = None,
110
+ wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
111
+ ) -> Self:
112
+ return cls(
113
+ personal_access_token=personal_access_token,
114
+ workspace_id=workspace_id,
115
+ endpoint=endpoint,
116
+ wait_for_action_attempt=wait_for_action_attempt,
117
+ )
99
118
  `
@@ -3,7 +3,4 @@ import { pascalCase } from "change-case"
3
3
  export default (namespaces: string[]) => `@dataclass
4
4
  class AbstractRoutes(abc.ABC):
5
5
  ${namespaces.map((ns) => ` ${ns}: Abstract${pascalCase(ns)}`).join("\n")}
6
-
7
- @abc.abstractmethod
8
- def make_request(self, method: str, path: str, **kwargs) -> Any:
9
- raise NotImplementedError`
6
+ `
@@ -1,18 +1,43 @@
1
- export default () => `@dataclass
2
- class AbstractSeam(AbstractRoutes):
3
- api_key: str
4
- workspace_id: str
5
- api_url: str
1
+ export default () => `class AbstractSeam(AbstractRoutes):
6
2
  lts_version: str
7
- wait_for_action_attempt: bool
8
3
 
9
4
  @abc.abstractmethod
10
5
  def __init__(
11
6
  self,
12
7
  api_key: Optional[str] = None,
13
8
  *,
9
+ personal_access_token: Optional[str] = None,
14
10
  workspace_id: Optional[str] = None,
15
- api_url: Optional[str] = None,
16
- wait_for_action_attempt: Optional[bool] = False,
11
+ endpoint: Optional[str] = None,
12
+ wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
17
13
  ):
18
- raise NotImplementedError`
14
+ self.wait_for_action_attempt = wait_for_action_attempt
15
+ self.lts_version = AbstractSeam.lts_version
16
+
17
+ @abc.abstractmethod
18
+ def make_request(self, method: str, path: str, **kwargs) -> Any:
19
+ raise NotImplementedError
20
+
21
+ @classmethod
22
+ @abc.abstractmethod
23
+ def from_api_key(
24
+ cls,
25
+ api_key: str,
26
+ *,
27
+ endpoint: Optional[str] = None,
28
+ wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
29
+ ) -> Self:
30
+ raise NotImplementedError
31
+
32
+ @classmethod
33
+ @abc.abstractmethod
34
+ def from_personal_access_token(
35
+ cls,
36
+ personal_access_token: str,
37
+ workspace_id: str,
38
+ *,
39
+ endpoint: Optional[str] = None,
40
+ wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = False,
41
+ ) -> Self:
42
+ raise NotImplementedError
43
+ `
@@ -0,0 +1,48 @@
1
+ export default () => `token_prefix = "seam_"
2
+
3
+ access_token_prefix = "seam_at"
4
+
5
+ jwt_prefix = "ey"
6
+
7
+ client_session_token_prefix = "seam_cst"
8
+
9
+ publishable_key_token_prefix = "seam_pk"
10
+
11
+
12
+ def is_access_token(token: str) -> bool:
13
+ return token.startswith(access_token_prefix)
14
+
15
+
16
+ def is_jwt(token: str) -> bool:
17
+ return token.startswith(jwt_prefix)
18
+
19
+
20
+ def is_seam_token(token: str) -> bool:
21
+ return token.startswith(token_prefix)
22
+
23
+
24
+ def is_api_key(token: str) -> bool:
25
+ return (
26
+ not is_client_session_token(token)
27
+ and not is_jwt(token)
28
+ and not is_access_token(token)
29
+ and not is_publishable_key(token)
30
+ and is_seam_token(token)
31
+ )
32
+
33
+
34
+ def is_client_session_token(token: str) -> bool:
35
+ return token.startswith(client_session_token_prefix)
36
+
37
+
38
+ def is_publishable_key(token: str) -> bool:
39
+ return token.startswith(publishable_key_token_prefix)
40
+
41
+
42
+ def is_console_session_token(token: str) -> bool:
43
+ return is_jwt(token)
44
+
45
+
46
+ def is_personal_access_token(token: str) -> bool:
47
+ return is_access_token(token)
48
+ `