Skip to content

Commit ef72b48

Browse files
committed
feat(sdk/sdk): python client
1 parent f45e67b commit ef72b48

File tree

3 files changed

+168
-11
lines changed

3 files changed

+168
-11
lines changed

typegraph/python/typegraph/graph/tg_deploy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from urllib import request
77
import json
88
from base64 import b64encode
9-
from typegraph.gen.exports.core import ArtifactResolutionConfig
9+
from typegraph.wit import ArtifactResolutionConfig
1010
from typegraph.gen.types import Err
1111

1212
from typegraph.graph.typegraph import TypegraphOutput
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0.
2+
# SPDX-License-Identifier: MPL-2.0
3+
4+
from ctypes import Union
5+
from dataclasses import dataclass
6+
from enum import Enum
7+
import os
8+
from typing import TYPE_CHECKING, Dict
9+
import json
10+
from typegraph.gen.exports.core import MigrationAction, MigrationConfig
11+
12+
from typegraph.graph.tg_deploy import BasicAuth
13+
from typegraph.wit import ArtifactResolutionConfig
14+
from urllib import request
15+
16+
if TYPE_CHECKING:
17+
from typegraph.graph.typegraph import TypegraphOutput
18+
19+
20+
VERSION = "0.3.5-0"
21+
PORT = "META_CLI_SERVER_PORT" # meta-cli instance that executes the current file
22+
SELF_PATH = (
23+
"META_CLI_TG_PATH" # path to the current file to uniquely identify the run results
24+
)
25+
26+
27+
class Command(Enum):
28+
SERIALIZE = "serialize"
29+
DEPLOY = "deploy"
30+
UNPACK_MIGRATION = "unpack_migration"
31+
32+
33+
# Types for CLI => SDK
34+
@dataclass
35+
class Typegate:
36+
endpoint: str
37+
auth: Union[None, BasicAuth] = None
38+
39+
40+
@dataclass
41+
class CLIConfigRequest:
42+
typegate: Typegate
43+
prefix: Union[None, str] = None
44+
secrets: Dict[str, str]
45+
artifacts_config: ArtifactResolutionConfig
46+
47+
48+
@dataclass
49+
class CLIServerResponse:
50+
command: Command
51+
config: CLIConfigRequest
52+
53+
54+
class Manager:
55+
port: int
56+
typegraph: TypegraphOutput
57+
endpoint: str
58+
typegraph_path: str
59+
60+
def is_run_from_cli() -> bool:
61+
return True if os.environ.get(PORT) else False
62+
63+
def __init__(self, typegraph: TypegraphOutput, port: Union[None, int] = None):
64+
self.typegraph = typegraph
65+
self.typegraph_path = os.environ.get(SELF_PATH)
66+
if port is None:
67+
self.port = int(os.environ.get(PORT))
68+
else:
69+
self.port = port
70+
self.endpoint = f"http://localhost:{self.port}"
71+
72+
def run(self):
73+
sdk = self.request_command()
74+
if sdk.command == Command.SERIALIZE:
75+
self.serialize(sdk.config)
76+
elif sdk.command == Command.DEPLOY:
77+
self.deploy(sdk.config)
78+
elif sdk.command == Command.UNPACK_MIGRATION:
79+
self.unpack_migration(sdk.config)
80+
else:
81+
raise Exception(f"command {sdk.command.value} not supported")
82+
83+
def serialize(self, config: CLIConfigRequest):
84+
def fn():
85+
artifact_cfg = config.artifacts_config
86+
artifact_cfg.prefix = (
87+
config.prefix
88+
) # prefix from cli overrides the current value
89+
return self.typegraph.serialize(artifact_cfg)
90+
91+
return self.relay_result_to_cli(command=Command.SERIALIZE, fn=fn)
92+
93+
def deploy(config: CLIConfigRequest):
94+
pass
95+
96+
def unpack_migration(config: CLIConfigRequest):
97+
pass
98+
99+
def request_command(self) -> CLIServerResponse:
100+
config = self.request_config()
101+
req = request.Request(f"{self.endpoint}/command")
102+
raw = request.urlopen(req).read().decode()
103+
return CLIServerResponse(command=Command(raw["command"]), config=config)
104+
105+
def request_config(self) -> CLIConfigRequest:
106+
tg_name = self.typegraph.name
107+
req = request.Request(f"{self.endpoint}/config?typegraph={tg_name}")
108+
raw = request.urlopen(req).read().decode()
109+
cli_res = json.loads(raw)
110+
111+
prefix = None
112+
if "prefix" in cli_res:
113+
prefix = cli_res["prefix"]
114+
115+
auth = None
116+
if "auth" in cli_res["endpoint"]:
117+
auth = BasicAuth(
118+
cli_res["endpoint"]["username"], cli_res["endpoint"]["password"]
119+
)
120+
121+
artifact_config_raw = cli_res["artifactsConfig"]
122+
return CLIConfigRequest(
123+
typegate=Typegate(endpoint=cli_res["endpoint"]["typegate"], auth=auth),
124+
prefix=prefix,
125+
secrets=cli_res["secrets"],
126+
artifacts_config=ArtifactResolutionConfig(
127+
dir=artifact_config_raw["dir"],
128+
prefix=prefix,
129+
prisma_migration=MigrationConfig(
130+
action=MigrationAction(
131+
create=artifact_config_raw["prismaMigration"]["action"][
132+
"create"
133+
],
134+
reset=artifact_config_raw["prismaMigration"]["action"]["reset"],
135+
),
136+
migration_dir=artifact_config_raw["prismaMigration"][
137+
"migrationDir"
138+
],
139+
),
140+
),
141+
)
142+
143+
def relay_result_to_cli(self, initiator: Command, fn: callable):
144+
response = {
145+
"command": initiator.value,
146+
"typegraphName": self.typegraph.name,
147+
"typegraphPath": self.typegraph_path,
148+
}
149+
try:
150+
response["data"] = fn()
151+
except Exception as e:
152+
response["error"] = str(e)
153+
154+
req = request.Request(
155+
url=f"{self.endpoint}/response",
156+
method="POST",
157+
headers={"Content-Type": "application/json"},
158+
data=json.dumps(response),
159+
)
160+
161+
request.urlopen(req)

typegraph/python/typegraph/graph/typegraph.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from typegraph.gen.types import Err
1919
from typegraph.graph.params import Auth, Cors, RawAuth
20+
from typegraph.graph.tg_manage import Manager
2021
from typegraph.policy import Policy, PolicyPerEffect, PolicySpec, get_policy_chain
2122
from typegraph.wit import core, store, wit_utils
2223

@@ -181,7 +182,6 @@ def typegraph(
181182
rate: Optional[Rate] = None,
182183
cors: Optional[Cors] = None,
183184
prefix: Optional[str] = None,
184-
disable_auto_serialization: Optional[bool] = False,
185185
) -> Callable[[Callable[[Graph], None]], Callable[[], TypegraphOutput]]:
186186
def decorator(builder: Callable[[Graph], None]) -> TypegraphOutput:
187187
actual_name = name
@@ -227,16 +227,12 @@ def serialize_with_artifacts(
227227
raise Exception(tg_json.value)
228228
return tg_json.value
229229

230-
# TODO: remove
231-
# print(serialize_with_artifacts(config=ArtifactResolutionConfig(
232-
# dir=".",
233-
# prisma_migration=MigrationConfig(
234-
# action=MigrationAction(create=True, reset=True),
235-
# migration_dir="."
236-
# )
237-
# )))
230+
tg_output = TypegraphOutput(name=tg.name, serialize=serialize_with_artifacts)
231+
if Manager.is_run_from_cli():
232+
manager = Manager(tg_output)
233+
manager.run()
238234

239-
return lambda: TypegraphOutput(name=tg.name, serialize=serialize_with_artifacts)
235+
return lambda: tg_output
240236

241237
return decorator
242238

0 commit comments

Comments
 (0)