jac-scale 0.1.1__tar.gz → 0.1.3__tar.gz
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.
- {jac_scale-0.1.1 → jac_scale-0.1.3}/PKG-INFO +9 -2
- {jac_scale-0.1.1 → jac_scale-0.1.3}/README.md +7 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/abstractions/config/app_config.jac +5 -2
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/context.jac +2 -1
- jac_scale-0.1.3/jac_scale/factories/storage_factory.jac +75 -0
- jac_scale-0.1.3/jac_scale/google_sso_provider.jac +85 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/impl/context.impl.jac +3 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/impl/serve.impl.jac +82 -234
- jac_scale-0.1.3/jac_scale/impl/user_manager.impl.jac +349 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/memory_hierarchy.jac +3 -1
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/plugin.jac +46 -3
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/plugin_config.jac +27 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/serve.jac +3 -12
- jac_scale-0.1.3/jac_scale/sso_provider.jac +72 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/targets/kubernetes/kubernetes_config.jac +9 -15
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/targets/kubernetes/kubernetes_target.jac +174 -15
- jac_scale-0.1.3/jac_scale/tests/fixtures/scale-feats/components/Button.cl.jac +32 -0
- jac_scale-0.1.3/jac_scale/tests/fixtures/scale-feats/main.jac +147 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/fixtures/test_api.jac +29 -0
- jac_scale-0.1.3/jac_scale/tests/fixtures/test_restspec.jac +37 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/test_deploy_k8s.py +2 -1
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/test_examples.py +180 -5
- jac_scale-0.1.3/jac_scale/tests/test_hooks.py +39 -0
- jac_scale-0.1.3/jac_scale/tests/test_restspec.py +192 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/test_serve.py +54 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/test_sso.py +273 -284
- jac_scale-0.1.3/jac_scale/tests/test_storage.py +274 -0
- jac_scale-0.1.3/jac_scale/user_manager.jac +49 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale.egg-info/PKG-INFO +9 -2
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale.egg-info/SOURCES.txt +11 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale.egg-info/requires.txt +1 -1
- {jac_scale-0.1.1 → jac_scale-0.1.3}/pyproject.toml +2 -2
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/__init__.py +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/abstractions/config/base_config.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/abstractions/database_provider.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/abstractions/deployment_target.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/abstractions/image_registry.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/abstractions/logger.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/abstractions/models/deployment_result.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/abstractions/models/resource_status.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/config_loader.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/factories/database_factory.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/factories/deployment_factory.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/factories/registry_factory.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/factories/utility_factory.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/impl/config_loader.impl.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/impl/memory_hierarchy.main.impl.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/impl/memory_hierarchy.mongo.impl.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/impl/memory_hierarchy.redis.impl.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/jserver/__init__.py +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/jserver/impl/jfast_api.impl.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/jserver/impl/jserver.impl.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/jserver/jfast_api.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/jserver/jserver.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/providers/database/kubernetes_mongo.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/providers/database/kubernetes_redis.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/providers/registry/dockerhub.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/targets/kubernetes/utils/kubernetes_utils.impl.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/targets/kubernetes/utils/kubernetes_utils.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/__init__.py +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/conftest.py +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/fixtures/todo_app.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/test_abstractions.py +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/test_factories.py +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/test_file_upload.py +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/test_k8s_utils.py +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/tests/test_memory_hierarchy.py +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/utilities/loggers/standard_logger.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale/utils.jac +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale.egg-info/dependency_links.txt +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale.egg-info/entry_points.txt +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/jac_scale.egg-info/top_level.txt +0 -0
- {jac_scale-0.1.1 → jac_scale-0.1.3}/setup.cfg +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jac-scale
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Author-email: Jason Mars <jason@mars.ninja>
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: jaclang>=0.9.
|
|
7
|
+
Requires-Dist: jaclang>=0.9.12
|
|
8
8
|
Requires-Dist: python-dotenv<2.0.0,>=1.2.1
|
|
9
9
|
Requires-Dist: docker<8.0.0,>=7.1.0
|
|
10
10
|
Requires-Dist: kubernetes<35.0.0,>=34.1.0
|
|
@@ -43,6 +43,13 @@ Requires-Dist: python-multipart<1.0.0,>=0.0.21
|
|
|
43
43
|
|
|
44
44
|
Whether you're developing locally with `jac start` or deploying to production with `jac start --scale`, you get the same powerful features with the flexibility to choose your deployment strategy.
|
|
45
45
|
|
|
46
|
+
### 4. Single Sign-On (SSO) Support
|
|
47
|
+
|
|
48
|
+
- **Google SSO**: Built-in support for Google Sign-In out of the box
|
|
49
|
+
- **Extensible Architecture**: Easily add other providers (GitHub, Microsoft, etc.)
|
|
50
|
+
- **Secure Authentication**: Integrated with JWT for secure session management
|
|
51
|
+
- **User Management**: Automatic account creation and linking
|
|
52
|
+
|
|
46
53
|
## Prerequisites
|
|
47
54
|
|
|
48
55
|
- kubenetes(K8s) installed
|
|
@@ -25,6 +25,13 @@
|
|
|
25
25
|
|
|
26
26
|
Whether you're developing locally with `jac start` or deploying to production with `jac start --scale`, you get the same powerful features with the flexibility to choose your deployment strategy.
|
|
27
27
|
|
|
28
|
+
### 4. Single Sign-On (SSO) Support
|
|
29
|
+
|
|
30
|
+
- **Google SSO**: Built-in support for Google Sign-In out of the box
|
|
31
|
+
- **Extensible Architecture**: Easily add other providers (GitHub, Microsoft, etc.)
|
|
32
|
+
- **Secure Authentication**: Integrated with JWT for secure session management
|
|
33
|
+
- **User Management**: Automatic account creation and linking
|
|
34
|
+
|
|
28
35
|
## Prerequisites
|
|
29
36
|
|
|
30
37
|
- kubenetes(K8s) installed
|
|
@@ -7,7 +7,8 @@ class AppConfig {
|
|
|
7
7
|
file_name: str = 'none',
|
|
8
8
|
build: bool = False,
|
|
9
9
|
app_name: (str | None) = None,
|
|
10
|
-
testing: bool = False
|
|
10
|
+
testing: bool = False,
|
|
11
|
+
experimental: bool = False;
|
|
11
12
|
|
|
12
13
|
def init(
|
|
13
14
|
self: AppConfig,
|
|
@@ -15,13 +16,15 @@ class AppConfig {
|
|
|
15
16
|
file_name: str = 'none',
|
|
16
17
|
build: bool = False,
|
|
17
18
|
app_name: (str | None) = None,
|
|
18
|
-
testing: bool = False
|
|
19
|
+
testing: bool = False,
|
|
20
|
+
experimental: bool = False
|
|
19
21
|
) -> None {
|
|
20
22
|
self.code_folder = code_folder;
|
|
21
23
|
self.file_name = file_name;
|
|
22
24
|
self.build = build;
|
|
23
25
|
self.app_name = app_name;
|
|
24
26
|
self.testing = testing;
|
|
27
|
+
self.experimental = experimental;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
def get_code_path(self: AppConfig) -> Path {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import from contextvars { ContextVar }
|
|
1
2
|
import from dataclasses { MISSING }
|
|
2
3
|
import from typing { Any }
|
|
3
4
|
import from uuid { UUID }
|
|
4
5
|
import from jaclang.pycore.constant { Constants as Con }
|
|
5
|
-
import from jaclang.runtimelib.context { ExecutionContext }
|
|
6
|
+
import from jaclang.runtimelib.context { ExecutionContext, CallState }
|
|
6
7
|
|
|
7
8
|
"""Jac Scale Execution Context with custom memory backend.
|
|
8
9
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Factory for creating storage instances."""
|
|
2
|
+
import from typing { Any }
|
|
3
|
+
import os;
|
|
4
|
+
import from jaclang.runtimelib.storage { Storage }
|
|
5
|
+
import from jaclang.project.config { get_config }
|
|
6
|
+
|
|
7
|
+
enum StorageType {
|
|
8
|
+
LOCAL = "local"
|
|
9
|
+
# Future: S3, GCS, AZURE - add when implemented
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
"""Factory for creating storage instances.
|
|
13
|
+
|
|
14
|
+
Configuration priority: jac.toml > environment variable > default
|
|
15
|
+
|
|
16
|
+
In jac.toml:
|
|
17
|
+
[storage]
|
|
18
|
+
type = "local" # or "s3", "gcs", "azure"
|
|
19
|
+
base_path = "/data/storage"
|
|
20
|
+
create_dirs = true
|
|
21
|
+
|
|
22
|
+
Environment variables:
|
|
23
|
+
JAC_STORAGE_TYPE: Storage type (local, s3, gcs, azure)
|
|
24
|
+
JAC_STORAGE_PATH: Base directory for local storage
|
|
25
|
+
JAC_STORAGE_CREATE_DIRS: Whether to auto-create directories
|
|
26
|
+
"""
|
|
27
|
+
class StorageFactory {
|
|
28
|
+
static def create(
|
|
29
|
+
storage_type: (StorageType | str), config: (dict[str, Any] | None) = None
|
|
30
|
+
) -> Storage {
|
|
31
|
+
# Convert string to enum if needed
|
|
32
|
+
if isinstance(storage_type, str) {
|
|
33
|
+
storage_type = StorageType(storage_type);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if storage_type == StorageType.LOCAL {
|
|
37
|
+
import from jaclang.runtimelib.storage { LocalStorage }
|
|
38
|
+
cfg = config or {};
|
|
39
|
+
return LocalStorage(
|
|
40
|
+
base_path=cfg.get("base_path", "./storage"),
|
|
41
|
+
create_dirs=cfg.get("create_dirs", True)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
raise ValueError(f"Unsupported storage type: {storage_type}") ;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static def get_default(
|
|
48
|
+
base_path: str = "./storage", create_dirs: bool = True
|
|
49
|
+
) -> Storage {
|
|
50
|
+
# Get config from jac.toml if available
|
|
51
|
+
jac_config = get_config();
|
|
52
|
+
|
|
53
|
+
# Config priority: jac.toml > env var > parameter
|
|
54
|
+
if jac_config and jac_config.storage {
|
|
55
|
+
storage_type = StorageType(jac_config.storage.storage_type);
|
|
56
|
+
base_path = jac_config.storage.base_path;
|
|
57
|
+
create_dirs = jac_config.storage.create_dirs;
|
|
58
|
+
} elif os.environ.get("JAC_STORAGE_TYPE") or os.environ.get("JAC_STORAGE_PATH") {
|
|
59
|
+
storage_type_str = os.environ.get(
|
|
60
|
+
"JAC_STORAGE_TYPE", StorageType.LOCAL.value
|
|
61
|
+
);
|
|
62
|
+
storage_type = StorageType(storage_type_str);
|
|
63
|
+
base_path = os.environ.get("JAC_STORAGE_PATH", base_path);
|
|
64
|
+
create_dirs_str = os.environ.get(
|
|
65
|
+
"JAC_STORAGE_CREATE_DIRS", str(create_dirs)
|
|
66
|
+
);
|
|
67
|
+
create_dirs = create_dirs_str.lower() == "true";
|
|
68
|
+
} else {
|
|
69
|
+
storage_type = StorageType.LOCAL;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
storage_config = {"base_path": base_path, "create_dirs": create_dirs};
|
|
73
|
+
return StorageFactory.create(storage_type, storage_config);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Google SSO Provider implementation for jac-scale.
|
|
2
|
+
|
|
3
|
+
This module implements the SSOProvider interface for Google OAuth authentication.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import from fastapi { Request, Response }
|
|
7
|
+
import from fastapi_sso.sso.google { GoogleSSO }
|
|
8
|
+
import from jac_scale.sso_provider { SSOProvider, SSOUserInfo }
|
|
9
|
+
|
|
10
|
+
"""Google OAuth SSO Provider.
|
|
11
|
+
|
|
12
|
+
This class wraps the fastapi_sso GoogleSSO implementation to conform to
|
|
13
|
+
our SSOProvider interface, enabling consistent handling across all SSO vendors.
|
|
14
|
+
"""
|
|
15
|
+
obj GoogleSSOProvider(SSOProvider) {
|
|
16
|
+
has client_id: str,
|
|
17
|
+
client_secret: str,
|
|
18
|
+
redirect_uri: str,
|
|
19
|
+
allow_insecure_http: bool = True,
|
|
20
|
+
_google_sso: (GoogleSSO | None) = None;
|
|
21
|
+
|
|
22
|
+
"""Initialize the Google SSO provider."""
|
|
23
|
+
def postinit -> None {
|
|
24
|
+
self._google_sso = GoogleSSO(
|
|
25
|
+
client_id=self.client_id,
|
|
26
|
+
client_secret=self.client_secret,
|
|
27
|
+
redirect_uri=self.redirect_uri,
|
|
28
|
+
allow_insecure_http=self.allow_insecure_http
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
"""Initiate Google OAuth authentication flow.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
operation: The operation type ('login' or 'register')
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
RedirectResponse to Google's OAuth authorization page
|
|
39
|
+
"""
|
|
40
|
+
async def initiate_auth(operation: str) -> Response {
|
|
41
|
+
if not self._google_sso {
|
|
42
|
+
raise RuntimeError("GoogleSSO not initialized") ;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
with self._google_sso {
|
|
46
|
+
return await self._google_sso.get_login_redirect();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
"""Handle the OAuth callback from Google.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
request: The FastAPI request object containing OAuth callback data
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
SSOUserInfo: Standardized user information from Google
|
|
57
|
+
|
|
58
|
+
Raises:
|
|
59
|
+
Exception: If authentication fails or user info cannot be retrieved
|
|
60
|
+
"""
|
|
61
|
+
async def handle_callback(request: Request) -> SSOUserInfo {
|
|
62
|
+
if not self._google_sso {
|
|
63
|
+
raise RuntimeError("GoogleSSO not initialized") ;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
with self._google_sso {
|
|
67
|
+
user_info = await self._google_sso.verify_and_process(request);
|
|
68
|
+
return SSOUserInfo(
|
|
69
|
+
email=user_info.email,
|
|
70
|
+
external_id=user_info.id,
|
|
71
|
+
platform=self.get_platform_name(),
|
|
72
|
+
display_name=user_info?.display_name
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
"""Get the platform identifier.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
str: 'google'
|
|
81
|
+
"""
|
|
82
|
+
def get_platform_name -> str {
|
|
83
|
+
return "google";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -21,4 +21,7 @@ impl JScaleExecutionContext.init(self: JScaleExecutionContext) -> None {
|
|
|
21
21
|
# Default user_root and entry_node to system_root
|
|
22
22
|
self.user_root = self.system_root;
|
|
23
23
|
self.entry_node = self.system_root;
|
|
24
|
+
self.call_state: ContextVar[CallState] = ContextVar(
|
|
25
|
+
'call_state', default=CallState()
|
|
26
|
+
);
|
|
24
27
|
}
|