ts-lib-artifacts 0.1.0__py3-none-any.whl

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 (146) hide show
  1. ts_lib_artifacts/README.md +8 -0
  2. ts_lib_artifacts/__init__.py +0 -0
  3. ts_lib_artifacts/artifacts/README.md +37 -0
  4. ts_lib_artifacts/artifacts/__init__.py +7 -0
  5. ts_lib_artifacts/artifacts/artifact_template.py +15 -0
  6. ts_lib_artifacts/artifacts/connector/README.md +23 -0
  7. ts_lib_artifacts/artifacts/connector/__init__.py +32 -0
  8. ts_lib_artifacts/artifacts/data_app/README.md +43 -0
  9. ts_lib_artifacts/artifacts/data_app/__init__.py +137 -0
  10. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/cookiecutter.json +14 -0
  11. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/.dockerignore +10 -0
  12. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/.env.example +15 -0
  13. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/.gitignore +563 -0
  14. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/.yarnrc.yml +5 -0
  15. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/CONTRIBUTING.md +163 -0
  16. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/Dockerfile +86 -0
  17. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/README.md +56 -0
  18. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/conf/supervisord-local.conf +20 -0
  19. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/conf/supervisord.conf +20 -0
  20. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/docs/README.md +16 -0
  21. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/docs/health-service.md +95 -0
  22. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/docs/jwt-token-manager.md +148 -0
  23. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/docs/tdp-api-integration.md +128 -0
  24. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/docs/tetrascience-react-ui.md +72 -0
  25. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/images/icon.png +0 -0
  26. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/manifest.json +34 -0
  27. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/package.json +34 -0
  28. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/eslint.config.js +33 -0
  29. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/index.html +15 -0
  30. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/package.json +53 -0
  31. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/src/App.css +96 -0
  32. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/src/App.tsx +77 -0
  33. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/src/api.ts +11 -0
  34. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/src/examples/DataAppsApiExample.tsx +39 -0
  35. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/src/index.css +73 -0
  36. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/src/main.tsx +16 -0
  37. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/src/vite-env.d.ts +1 -0
  38. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/tests/browser/HelloWorld.spec.tsx +9 -0
  39. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/tests/unit/__snapshots__/basic.test.tsx.snap +7 -0
  40. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/tests/unit/basic.test.tsx +15 -0
  41. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/tsconfig.app.json +35 -0
  42. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/tsconfig.json +8 -0
  43. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/tsconfig.node.json +24 -0
  44. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/vite.config.ts +24 -0
  45. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/vitest.config.ts +49 -0
  46. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/client/vitest.shims.d.ts +1 -0
  47. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/server/package.json +50 -0
  48. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/server/src/app.ts +245 -0
  49. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/server/src/config.ts +50 -0
  50. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/server/src/index.ts +26 -0
  51. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/server/src/services/health-service.ts +189 -0
  52. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/packages/server/tsconfig.json +26 -0
  53. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/scripts/setup-env.js +41 -0
  54. ts_lib_artifacts/artifacts/data_app/templates/react/4.3/{{ cookiecutter._project_dir }}/yarn.lock +3 -0
  55. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/cookiecutter.json +14 -0
  56. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/.dockerignore +46 -0
  57. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/.gitignore +544 -0
  58. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/.streamlit/config-docker.toml +18 -0
  59. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/.streamlit/config.toml +16 -0
  60. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/CONTRIBUTING.md +45 -0
  61. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/Dockerfile +74 -0
  62. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/README.md +58 -0
  63. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/app.py +4 -0
  64. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/conf/supervisord-local.conf +18 -0
  65. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/conf/supervisord.conf +31 -0
  66. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/heartbeat.py +51 -0
  67. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/images/icon.png +0 -0
  68. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/manifest.json +30 -0
  69. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/{{ cookiecutter.data_app._package_dir }}/__init__.py +0 -0
  70. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/{{ cookiecutter.data_app._package_dir }}/main.py +758 -0
  71. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/{{ cookiecutter.data_app._package_dir }}/style.css +13 -0
  72. ts_lib_artifacts/artifacts/data_app/templates/streamlit/4.3/{{ cookiecutter._project_dir }}/{{/"pyproject.toml/"}}" +84 -0
  73. ts_lib_artifacts/artifacts/ids/README.md +35 -0
  74. ts_lib_artifacts/artifacts/ids/__init__.py +72 -0
  75. ts_lib_artifacts/artifacts/ids/patches.py +71 -0
  76. ts_lib_artifacts/artifacts/ids/templates/default/3.5/cookiecutter.json +8 -0
  77. ts_lib_artifacts/artifacts/ids/templates/default/3.5/{{ cookiecutter._project_dir }}/README.md +3 -0
  78. ts_lib_artifacts/artifacts/ids/templates/default/3.5/{{ cookiecutter._project_dir }}/athena.json +4 -0
  79. ts_lib_artifacts/artifacts/ids/templates/default/3.5/{{ cookiecutter._project_dir }}/elasticsearch.json +11 -0
  80. ts_lib_artifacts/artifacts/ids/templates/default/3.5/{{ cookiecutter._project_dir }}/expected.json +11 -0
  81. ts_lib_artifacts/artifacts/ids/templates/default/3.5/{{ cookiecutter._project_dir }}/schema.json +64 -0
  82. ts_lib_artifacts/artifacts/pipeline_artifact.py +35 -0
  83. ts_lib_artifacts/artifacts/protocol/README.md +32 -0
  84. ts_lib_artifacts/artifacts/protocol/__init__.py +82 -0
  85. ts_lib_artifacts/artifacts/protocol/patches.py +42 -0
  86. ts_lib_artifacts/artifacts/protocol/templates/default/3.5/cookiecutter.json +14 -0
  87. ts_lib_artifacts/artifacts/protocol/templates/default/3.5/{{ cookiecutter._project_dir }}/README.md +3 -0
  88. ts_lib_artifacts/artifacts/protocol/templates/default/3.5/{{ cookiecutter._project_dir }}/protocol.json +34 -0
  89. ts_lib_artifacts/artifacts/protocol/templates/default/3.5/{{ cookiecutter._project_dir }}/script.js +22 -0
  90. ts_lib_artifacts/artifacts/protocol/templates/default/3.6/cookiecutter.json +14 -0
  91. ts_lib_artifacts/artifacts/protocol/templates/default/3.6/{{ cookiecutter._project_dir }}/README.md +3 -0
  92. ts_lib_artifacts/artifacts/protocol/templates/default/3.6/{{ cookiecutter._project_dir }}/protocol.yml +31 -0
  93. ts_lib_artifacts/artifacts/protocol/validate_v3_protocol.py +40 -0
  94. ts_lib_artifacts/artifacts/schema/README.md +21 -0
  95. ts_lib_artifacts/artifacts/schema/__init__.py +36 -0
  96. ts_lib_artifacts/artifacts/schema/templates/default/4.4/cookiecutter.json +8 -0
  97. ts_lib_artifacts/artifacts/schema/templates/default/4.4/{{ cookiecutter._project_dir }}/README.md +13 -0
  98. ts_lib_artifacts/artifacts/schema/templates/default/4.4/{{ cookiecutter._project_dir }}/expected.csv +4 -0
  99. ts_lib_artifacts/artifacts/schema/templates/default/4.4/{{ cookiecutter._project_dir }}/manifest.json +10 -0
  100. ts_lib_artifacts/artifacts/schema/templates/default/4.4/{{ cookiecutter._project_dir }}/schema.yml +9 -0
  101. ts_lib_artifacts/artifacts/task_script/README.md +28 -0
  102. ts_lib_artifacts/artifacts/task_script/__init__.py +40 -0
  103. ts_lib_artifacts/artifacts/task_script/templates/default/3.5/cookiecutter.json +14 -0
  104. ts_lib_artifacts/artifacts/task_script/templates/default/3.5/{{ cookiecutter._project_dir }}/README.md +3 -0
  105. ts_lib_artifacts/artifacts/task_script/templates/default/3.5/{{ cookiecutter._project_dir }}/__test__/data/expected.json +4 -0
  106. ts_lib_artifacts/artifacts/task_script/templates/default/3.5/{{ cookiecutter._project_dir }}/__test__/data/input.json +3 -0
  107. ts_lib_artifacts/artifacts/task_script/templates/default/3.5/{{ cookiecutter._project_dir }}/__test__/test_business_logic.py +17 -0
  108. ts_lib_artifacts/artifacts/task_script/templates/default/3.5/{{ cookiecutter._project_dir }}/__test__/test_config.py +26 -0
  109. ts_lib_artifacts/artifacts/task_script/templates/default/3.5/{{ cookiecutter._project_dir }}/__test__/test_integration.py +27 -0
  110. ts_lib_artifacts/artifacts/task_script/templates/default/3.5/{{ cookiecutter._project_dir }}/config.json +14 -0
  111. ts_lib_artifacts/artifacts/task_script/templates/default/3.5/{{ cookiecutter._project_dir }}/main.py +58 -0
  112. ts_lib_artifacts/artifacts/task_script/templates/default/3.5/{{ cookiecutter._project_dir }}/pyproject.toml +24 -0
  113. ts_lib_artifacts/artifacts/tetraflow/README.md +22 -0
  114. ts_lib_artifacts/artifacts/tetraflow/__init__.py +18 -0
  115. ts_lib_artifacts/artifacts/tetraflow/templates/spark/4.1/cookiecutter.json +8 -0
  116. ts_lib_artifacts/artifacts/tetraflow/templates/spark/4.1/{{ cookiecutter._project_dir }}/manifest.json +8 -0
  117. ts_lib_artifacts/artifacts/tetraflow/templates/spark/4.1/{{ cookiecutter._project_dir }}/tetraflow.yml +46 -0
  118. ts_lib_artifacts/artifacts/tetraflow/templates/spark/4.3/cookiecutter.json +8 -0
  119. ts_lib_artifacts/artifacts/tetraflow/templates/spark/4.3/{{ cookiecutter._project_dir }}/manifest.json +8 -0
  120. ts_lib_artifacts/artifacts/tetraflow/templates/spark/4.3/{{ cookiecutter._project_dir }}/tetraflow.yml +46 -0
  121. ts_lib_artifacts/core/README.md +29 -0
  122. ts_lib_artifacts/core/__init__.py +33 -0
  123. ts_lib_artifacts/core/api/__init__.py +12 -0
  124. ts_lib_artifacts/core/api/api_config.py +44 -0
  125. ts_lib_artifacts/core/api/api_error.py +60 -0
  126. ts_lib_artifacts/core/api/arms.py +79 -0
  127. ts_lib_artifacts/core/api/artifact_service.py +116 -0
  128. ts_lib_artifacts/core/api/base_api.py +142 -0
  129. ts_lib_artifacts/core/api/data_apps_service.py +59 -0
  130. ts_lib_artifacts/core/api/pipeline.py +57 -0
  131. ts_lib_artifacts/core/api/progress_tracker.py +109 -0
  132. ts_lib_artifacts/core/api/ts_api.py +28 -0
  133. ts_lib_artifacts/core/artifact_key.py +34 -0
  134. ts_lib_artifacts/core/artifact_type/__init__.py +7 -0
  135. ts_lib_artifacts/core/artifact_type/artifact_type.py +123 -0
  136. ts_lib_artifacts/core/artifact_type/patch.py +73 -0
  137. ts_lib_artifacts/core/artifact_type/validation_result.py +35 -0
  138. ts_lib_artifacts/core/files/__init__.py +99 -0
  139. ts_lib_artifacts/core/templates/__init__.py +11 -0
  140. ts_lib_artifacts/core/templates/template_error.py +26 -0
  141. ts_lib_artifacts/core/templates/template_group.py +129 -0
  142. ts_lib_artifacts/core/templates/template_tag.py +102 -0
  143. ts_lib_artifacts/core/version/__init__.py +104 -0
  144. ts_lib_artifacts-0.1.0.dist-info/METADATA +57 -0
  145. ts_lib_artifacts-0.1.0.dist-info/RECORD +146 -0
  146. ts_lib_artifacts-0.1.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,8 @@
1
+ # `external` Package
2
+
3
+ This package contains all domain logic that lives outside the CLI's command-handling layer. It is split into two sub-packages:
4
+
5
+ - **`core`** — Framework-level abstractions (API client, base artifact type, file I/O, template engine) that are artifact-type-agnostic.
6
+ - **`artifacts`** — Concrete artifact type implementations (protocol, task-script, IDS, etc.) that plug into the core framework.
7
+
8
+ The separation keeps the CLI commands thin: they parse arguments and delegate to `external` for all platform interaction, validation, patching, and templating.
File without changes
@@ -0,0 +1,37 @@
1
+ # `external.artifacts` Package
2
+
3
+ Concrete artifact type implementations for the Tetra Data Platform. Each sub-package implements a single artifact kind by extending the base classes from `external.core`.
4
+
5
+ ## Artifact Types
6
+
7
+ | Type | Class | Base Class | Description |
8
+ |------|-------|------------|-------------|
9
+ | `protocol` | `Protocol` | `PipelineArtifact` | Protocols (master scripts) with v3 validation |
10
+ | `task-script` | `TaskScript` | `PipelineArtifact` | Task scripts used by protocols |
11
+ | `ids` | `IDS` | `PipelineArtifact` | Intermediate Data Schemas |
12
+ | `schema` | `Schema` | `ArtifactTemplateGroup` | Schemas with expected output files |
13
+ | `data-app` | `DataApp` | `ArtifactTemplateGroup` | Containerized data applications |
14
+ | `connector` | `Connector` | `ArtifactType` | Containerized connectors |
15
+ | `tetraflow` | `Tetraflow` | `ArtifactTemplateGroup` | Tetraflow artifacts |
16
+
17
+ ## Inheritance Hierarchy
18
+
19
+ ```
20
+ ArtifactType (core) TemplateGroup (core)
21
+ │ │
22
+ └──── ArtifactTemplateGroup ─┘ (artifact_template.py)
23
+ │
24
+ PipelineArtifact (pipeline_artifact.py)
25
+ │ │ │
26
+ Protocol TaskScript IDS
27
+ ```
28
+
29
+ - **`ArtifactTemplateGroup`** — combines `ArtifactType` + `TemplateGroup`, providing default template and environment schema behavior. Used directly by Schema, DataApp, and Tetraflow.
30
+ - **`PipelineArtifact`** — extends `ArtifactTemplateGroup` with pipeline-based dependency tracking (`get_dependents` queries pipelines that use the artifact). Used by Protocol, TaskScript, and IDS.
31
+
32
+ ## Structure
33
+
34
+ Each artifact sub-package typically contains:
35
+ - `__init__.py` — the artifact class implementation
36
+ - `templates/` — Jinja2 template directories organized by `<template_name>/<platform_version>/`
37
+ - Type-specific modules (e.g. `patches.py`, validation logic)
@@ -0,0 +1,7 @@
1
+ from .connector import Connector
2
+ from .data_app import DataApp
3
+ from .ids import IDS
4
+ from .protocol import Protocol
5
+ from .schema import Schema
6
+ from .task_script import TaskScript
7
+ from .tetraflow import Tetraflow
@@ -0,0 +1,15 @@
1
+ from abc import ABC
2
+
3
+ from ..core.artifact_type import ArtifactType
4
+ from ..core.templates import TemplateGroup
5
+
6
+
7
+ class ArtifactTemplateGroup(ArtifactType, TemplateGroup, ABC):
8
+
9
+ @property
10
+ def group_name(self) -> str:
11
+ return self.artifact_type
12
+
13
+ @property
14
+ def default_template(self) -> str:
15
+ return "default"
@@ -0,0 +1,23 @@
1
+ # Connector
2
+
3
+ Artifact type for containerized connectors that integrate external systems with the platform.
4
+
5
+ ## Class: `Connector`
6
+
7
+ Extends `ArtifactType` directly (no template support).
8
+
9
+ - **Type identifier**: `"connector"`
10
+ - **Max size**: unlimited
11
+
12
+ ## Validation
13
+
14
+ - Requires `image.tar` in the source directory (Docker image)
15
+
16
+ ## Patches
17
+
18
+ - `PyprojectToml` — standard pyproject.toml patching
19
+ - `PackageJson` — standard package.json patching
20
+
21
+ ## Notes
22
+
23
+ Connector has no templates, no dependency tracking, and no environment schema. It is the simplest containerized artifact type. Data apps are a subtype of connector on the platform side.
@@ -0,0 +1,32 @@
1
+ import os
2
+ from os import PathLike
3
+
4
+ from ...core.api import ApiConfigLike
5
+ from ...core.artifact_type import ArtifactType, ValidationResult
6
+ from ...core.artifact_type.patch import PackageJson, Patch, PyprojectToml
7
+
8
+
9
+ class Connector(ArtifactType):
10
+ @property
11
+ def artifact_type(self) -> str:
12
+ return "connector"
13
+
14
+ def validate_source(
15
+ self, path: PathLike, api_config: ApiConfigLike
16
+ ) -> ValidationResult:
17
+ package_content = os.listdir(path)
18
+ if "image.tar" not in package_content:
19
+ return ValidationResult(
20
+ errors=[
21
+ "Connector package must contain 'image.tar' containing the Connector's Docker image."
22
+ ]
23
+ )
24
+ return ValidationResult()
25
+
26
+ @property
27
+ def max_size(self) -> float:
28
+ return float("inf")
29
+
30
+ @property
31
+ def patches(self) -> list[Patch]:
32
+ return [PyprojectToml(), PackageJson()]
@@ -0,0 +1,43 @@
1
+ # Data App
2
+
3
+ Artifact type for containerized data applications deployed on the platform.
4
+
5
+ ## Class: `DataApp`
6
+
7
+ Extends `ArtifactTemplateGroup`.
8
+
9
+ - **Type identifier**: `"data-app"`
10
+ - **Legacy type**: `"connectors"`
11
+ - **Client type**: `"data-app"`
12
+ - **Max size**: unlimited
13
+
14
+ ## Validation
15
+
16
+ - Requires `image.tar` in the source directory (Docker image built via `poetry run poe build-for-publish`)
17
+ - Manifest must include a label `{"name": "subtype", "value": "data-app"}`
18
+
19
+ ## Patches
20
+
21
+ - `PyprojectToml` — standard pyproject.toml patching
22
+ - `PackageJson` — standard package.json patching
23
+
24
+ ## Manifest
25
+
26
+ Overrides `update_manifest` to set `type` to `"connector"` (data apps are a subtype of connector on the platform).
27
+
28
+ ## Dependencies
29
+
30
+ Queries the data apps API endpoint and matches by scope/slug/version.
31
+
32
+ ## Templates
33
+
34
+ | Template | Platform Versions |
35
+ |-----------|-------------------|
36
+ | streamlit | 4.3 |
37
+ | react | 4.3 |
38
+
39
+ Default template: `streamlit`.
40
+
41
+ ## Environment Decoration
42
+
43
+ `decorate_environment` derives additional template variables from the collected environment: `artifact_title`, `package_dir`, `package_name`, `semver_version`, and `pep_440_version`.
@@ -0,0 +1,137 @@
1
+ import os
2
+ from os import PathLike
3
+ from pathlib import Path
4
+
5
+ from ...core.api import ApiConfigLike, TsApi
6
+ from ...core.artifact_key import ArtifactKey
7
+ from ...core.artifact_type import ValidationResult
8
+ from ...core.artifact_type.patch import PackageJson, Patch, PyprojectToml
9
+ from ...core.files import Files
10
+ from ...core.version import version_to_pep_440
11
+ from ..artifact_template import ArtifactTemplateGroup
12
+
13
+
14
+ class DataApp(ArtifactTemplateGroup):
15
+
16
+ @property
17
+ def default_template(self) -> str:
18
+ return "streamlit"
19
+
20
+ @property
21
+ def template_group_directory(self) -> PathLike:
22
+ return Path(__file__).parent.joinpath("templates")
23
+
24
+ @property
25
+ def artifact_type(self) -> str:
26
+ return "data-app"
27
+
28
+ @property
29
+ def legacy_artifact_type(self) -> str:
30
+ return "connectors"
31
+
32
+ @property
33
+ def patches(self) -> list[Patch]:
34
+ return [PyprojectToml(), PackageJson()]
35
+
36
+ @staticmethod
37
+ def data_app_matches(artifact: ArtifactKey, data_app: dict) -> bool:
38
+ """
39
+ Check if a data app matches the artifact being unpublished.
40
+ Data apps have scope (namespace), version, and slug fields.
41
+ """
42
+ scope = data_app.get("scope", None)
43
+ slug = data_app.get("slug", None)
44
+ version = data_app.get("version", None)
45
+ return (
46
+ artifact.namespace == scope
47
+ and artifact.slug == slug
48
+ and artifact.version == version
49
+ )
50
+
51
+ def update_manifest(self, manifest: dict, artifact: ArtifactKey) -> None:
52
+ super().update_manifest(manifest, artifact)
53
+ manifest["type"] = "connector"
54
+
55
+ @property
56
+ def client_type(self) -> str:
57
+ return "data-app"
58
+
59
+ def get_dependents(self, artifact: ArtifactKey, api: TsApi) -> list[str]:
60
+ data_apps = []
61
+ next_page = 1
62
+ while next_page is not None:
63
+ page, next_page = api.data_apps.get_data_apps(page=next_page)
64
+ data_apps = data_apps + page
65
+
66
+ return [
67
+ f"data app: {app.get('name', 'Unknown')}"
68
+ for app in data_apps
69
+ if DataApp.data_app_matches(artifact, app)
70
+ ]
71
+
72
+ def validate_source(
73
+ self, path: PathLike, api_config: ApiConfigLike
74
+ ) -> ValidationResult:
75
+ # Check for image.tar (same as connector)
76
+ package_content = os.listdir(path)
77
+ if "image.tar" not in package_content:
78
+ return ValidationResult(
79
+ errors=[
80
+ "Data app package must contain 'image.tar'. "
81
+ "Build your data app first with: poetry run poe build-for-publish"
82
+ ]
83
+ )
84
+
85
+ # Check manifest has correct subtype label
86
+ manifest_path = Path(path, "manifest.json")
87
+ manifest = Files.json.load_dict(manifest_path) or {}
88
+ labels = manifest.get("labels", [])
89
+ labels = labels if isinstance(labels, list) else []
90
+ subtype_labels = [
91
+ label
92
+ for label in labels
93
+ if (isinstance(label, dict) and label.get("name") == "subtype")
94
+ ]
95
+
96
+ if not subtype_labels or subtype_labels[0].get("value") != "data-app":
97
+ return ValidationResult(
98
+ errors=[
99
+ "Data app manifest must include label: "
100
+ '{"name": "subtype", "value": "data-app"}'
101
+ ]
102
+ )
103
+ return ValidationResult()
104
+
105
+ @property
106
+ def max_size(self) -> float:
107
+ return float("inf")
108
+
109
+ def decorate_environment(self, environment: dict) -> dict:
110
+ data_app_group = environment.get("data_app")
111
+ namespace = data_app_group.get("namespace")
112
+ slug = data_app_group.get("slug")
113
+ artifact_version = data_app_group.get("version")
114
+ semver_version = artifact_version.removeprefix("v")
115
+ pep_440_version = version_to_pep_440(artifact_version)
116
+ package_directory = DataApp._data_app_package_dir(namespace, slug)
117
+ artifact_title = slug.replace("-", " ").title()
118
+ data_app_group.update(
119
+ {
120
+ "_artifact_title": artifact_title,
121
+ "_description": f"A {artifact_title} data app",
122
+ "_package_dir": package_directory,
123
+ "_package_name": package_directory.replace("_", "-"),
124
+ "_semver_version": semver_version,
125
+ "_pep_440_version": pep_440_version,
126
+ }
127
+ )
128
+ return environment
129
+
130
+ @staticmethod
131
+ def _data_app_package_dir(namespace: str, slug: str) -> str:
132
+ """Create the package directory name for data apps."""
133
+ slug_clean = slug.replace("-", "_")
134
+ if namespace == "common":
135
+ return f"ts_data_app_{slug_clean}"
136
+ namespace_clean = namespace.replace("-", "_")
137
+ return f"ts_{namespace_clean}_data_app_{slug_clean}"
@@ -0,0 +1,14 @@
1
+ {
2
+ "_project_dir": "project",
3
+ "data_app": {
4
+ "namespace": "common",
5
+ "slug": "example",
6
+ "version": "v0.1.0",
7
+ "_artifact_title": "",
8
+ "_description": "",
9
+ "_package_dir": "",
10
+ "_package_name": "",
11
+ "_semver_version": "",
12
+ "_pep_440_version": ""
13
+ }
14
+ }
@@ -0,0 +1,10 @@
1
+ *
2
+ !package.json
3
+ !yarn.lock
4
+ !packages
5
+ !manifest.json
6
+ !conf
7
+ !README.md
8
+ !images
9
+ !.yarnrc.yml
10
+ cspell.json
@@ -0,0 +1,15 @@
1
+ # Server environment variables for local development
2
+ #
3
+ # SETUP: Copy this file to .env.server and populate with your values:
4
+ # cp .env.example .env.server
5
+ #
6
+ # NOTE: Do NOT include /v1 suffix in TDP_ENDPOINT
7
+
8
+ TDP_ENDPOINT=https://api.tetrascience.com
9
+ ORG_SLUG=your-org-slug
10
+
11
+ # Extract from cookies in your browser:
12
+ # 1. Open TDP in your browser and log in
13
+ # 2. Open Developer Tools > Application > Cookies
14
+ # 3. Find the 'ts_auth_token' cookie and copy its value here
15
+ TS_AUTH_TOKEN=your-auth-token-here