unitysvc-services 0.2.3__tar.gz → 0.2.5__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.
Files changed (60) hide show
  1. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/PKG-INFO +5 -2
  2. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/README.md +4 -1
  3. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/docs/cli-reference.md +61 -14
  4. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/docs/data-structure.md +10 -2
  5. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/docs/file-schemas.md +11 -0
  6. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/docs/getting-started.md +8 -0
  7. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/docs/workflows.md +9 -0
  8. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/pyproject.toml +1 -1
  9. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/models/listing_v1.py +5 -6
  10. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/publisher.py +9 -0
  11. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/query.py +102 -258
  12. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services.egg-info/PKG-INFO +5 -2
  13. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/CONTRIBUTING.md +0 -0
  14. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/HISTORY.md +0 -0
  15. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/LICENSE +0 -0
  16. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/MANIFEST.in +0 -0
  17. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/docs/api-reference.md +0 -0
  18. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/docs/contributing.md +0 -0
  19. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/docs/development.md +0 -0
  20. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/docs/index.md +0 -0
  21. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/docs/installation.md +0 -0
  22. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/docs/usage.md +0 -0
  23. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/setup.cfg +0 -0
  24. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/__init__.py +0 -0
  25. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/cli.py +0 -0
  26. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/format_data.py +0 -0
  27. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/list.py +0 -0
  28. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/models/__init__.py +0 -0
  29. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/models/base.py +0 -0
  30. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/models/provider_v1.py +0 -0
  31. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/models/seller_v1.py +0 -0
  32. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/models/service_v1.py +0 -0
  33. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/populate.py +0 -0
  34. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/py.typed +0 -0
  35. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/scaffold.py +0 -0
  36. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/update.py +0 -0
  37. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/utils.py +0 -0
  38. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services/validator.py +0 -0
  39. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services.egg-info/SOURCES.txt +0 -0
  40. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services.egg-info/dependency_links.txt +0 -0
  41. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services.egg-info/entry_points.txt +0 -0
  42. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services.egg-info/requires.txt +0 -0
  43. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/src/unitysvc_services.egg-info/top_level.txt +0 -0
  44. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/__init__.py +0 -0
  45. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/README.md +0 -0
  46. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider1/README.md +0 -0
  47. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider1/provider.toml +0 -0
  48. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider1/services/service1/code-example.md +0 -0
  49. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider1/services/service1/service.toml +0 -0
  50. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider1/services/service1/svcreseller.toml +0 -0
  51. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider1/terms-of-service.md +0 -0
  52. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider2/README.md +0 -0
  53. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider2/provider.json +0 -0
  54. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider2/services/service2/code-example.md +0 -0
  55. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider2/services/service2/service.json +0 -0
  56. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider2/services/service2/svcreseller.json +0 -0
  57. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/provider2/terms-of-service.md +0 -0
  58. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/example_data/seller.json +0 -0
  59. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/test_utils.py +0 -0
  60. {unitysvc_services-0.2.3 → unitysvc_services-0.2.5}/tests/test_validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unitysvc-services
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: SDK for digital service providers on UnitySVC
5
5
  Author-email: Bo Peng <bo.peng@unitysvc.com>
6
6
  Maintainer-email: Bo Peng <bo.peng@unitysvc.com>
@@ -87,8 +87,11 @@ unitysvc_services publish
87
87
  # Or publish specific types only
88
88
  unitysvc_services publish providers
89
89
 
90
- # Verify
90
+ # Verify with default fields
91
91
  unitysvc_services query offerings
92
+
93
+ # Query with custom fields
94
+ unitysvc_services query providers --fields id,name,contact_email
92
95
  ```
93
96
 
94
97
  ## Key Features
@@ -45,8 +45,11 @@ unitysvc_services publish
45
45
  # Or publish specific types only
46
46
  unitysvc_services publish providers
47
47
 
48
- # Verify
48
+ # Verify with default fields
49
49
  unitysvc_services query offerings
50
+
51
+ # Query with custom fields
52
+ unitysvc_services query providers --fields id,name,contact_email
50
53
  ```
51
54
 
52
55
  ## Key Features
@@ -157,6 +157,8 @@ unitysvc_services list listings [DATA_DIR]
157
157
 
158
158
  Query data from UnitySVC backend API.
159
159
 
160
+ All query commands support field selection to customize output columns and pagination options.
161
+
160
162
  ### query providers
161
163
 
162
164
  ```bash
@@ -166,11 +168,13 @@ unitysvc_services query providers [OPTIONS]
166
168
  **Options:**
167
169
 
168
170
  - `--format, -f {table|json}` - Output format (default: table)
171
+ - `--fields FIELDS` - Comma-separated list of fields to display (default: id,name,display_name,status)
172
+ - `--skip SKIP` - Number of records to skip for pagination (default: 0)
173
+ - `--limit LIMIT` - Maximum number of records to return (default: 100)
169
174
 
170
- **Required Environment Variables:**
175
+ **Available Fields:**
171
176
 
172
- - `UNITYSVC_BASE_URL` - Backend API URL
173
- - `UNITYSVC_API_KEY` - API key for authentication
177
+ id, name, display_name, contact_email, secondary_contact_email, homepage, description, status, created_at, updated_at
174
178
 
175
179
  ### query sellers
176
180
 
@@ -178,42 +182,85 @@ unitysvc_services query providers [OPTIONS]
178
182
  unitysvc_services query sellers [OPTIONS]
179
183
  ```
180
184
 
185
+ **Options:**
186
+
187
+ - `--format, -f {table|json}` - Output format (default: table)
188
+ - `--fields FIELDS` - Comma-separated list of fields to display (default: id,name,display_name,seller_type)
189
+ - `--skip SKIP` - Number of records to skip for pagination (default: 0)
190
+ - `--limit LIMIT` - Maximum number of records to return (default: 100)
191
+
192
+ **Available Fields:**
193
+
194
+ id, name, display_name, seller_type, contact_email, secondary_contact_email, homepage, description, business_registration, tax_id, account_manager_id, created_at, updated_at, status
195
+
181
196
  ### query offerings
182
197
 
183
198
  ```bash
184
199
  unitysvc_services query offerings [OPTIONS]
185
200
  ```
186
201
 
202
+ **Options:**
203
+
204
+ - `--format, -f {table|json}` - Output format (default: table)
205
+ - `--fields FIELDS` - Comma-separated list of fields to display (default: id,service_name,service_type,provider_name,status)
206
+ - `--skip SKIP` - Number of records to skip for pagination (default: 0)
207
+ - `--limit LIMIT` - Maximum number of records to return (default: 100)
208
+
209
+ **Available Fields:**
210
+
211
+ id, definition_id, provider_id, status, price, service_name, service_type, provider_name
212
+
187
213
  ### query listings
188
214
 
189
215
  ```bash
190
216
  unitysvc_services query listings [OPTIONS]
191
217
  ```
192
218
 
193
- ### query interfaces
219
+ **Options:**
194
220
 
195
- ```bash
196
- unitysvc_services query interfaces [OPTIONS]
197
- ```
221
+ - `--format, -f {table|json}` - Output format (default: table)
222
+ - `--fields FIELDS` - Comma-separated list of fields to display (default: id,service_name,service_type,seller_name,listing_type,status)
223
+ - `--skip SKIP` - Number of records to skip for pagination (default: 0)
224
+ - `--limit LIMIT` - Maximum number of records to return (default: 100)
198
225
 
199
- Query access interfaces (private endpoint).
226
+ **Available Fields:**
200
227
 
201
- ### query documents
228
+ id, offering_id, seller_id, status, created_at, updated_at, parameters_schema, parameters_ui_schema, tags, service_name, service_type, provider_name, seller_name, listing_type
202
229
 
203
- ```bash
204
- unitysvc_services query documents [OPTIONS]
205
- ```
230
+ **Required Environment Variables:**
206
231
 
207
- Query documents (private endpoint).
232
+ - `UNITYSVC_BASE_URL` - Backend API URL
233
+ - `UNITYSVC_API_KEY` - API key for authentication
208
234
 
209
235
  **Examples:**
210
236
 
211
237
  ```bash
212
- # Table output
238
+ # Table output with default fields
213
239
  unitysvc_services query providers
214
240
 
215
241
  # JSON output
216
242
  unitysvc_services query offerings --format json
243
+
244
+ # Custom fields - show only specific columns
245
+ unitysvc_services query providers --fields id,name,contact_email
246
+
247
+ # Show all available fields for sellers
248
+ unitysvc_services query sellers --fields id,name,display_name,seller_type,contact_email,homepage,created_at,updated_at
249
+
250
+ # Custom fields for listings
251
+ unitysvc_services query listings --fields id,service_name,listing_type,status
252
+
253
+ # Retrieve more than 100 records
254
+ unitysvc_services query providers --limit 500
255
+
256
+ # Pagination: get second page of 100 records
257
+ unitysvc_services query offerings --skip 100 --limit 100
258
+
259
+ # Large dataset retrieval
260
+ unitysvc_services query listings --limit 1000
261
+
262
+ # Combine pagination with custom fields
263
+ unitysvc_services query sellers --skip 50 --limit 50 --fields id,name,contact_email
217
264
  ```
218
265
 
219
266
  ## publish - Publish to Backend
@@ -80,6 +80,13 @@ data/
80
80
  - Location: `${provider_name}/services/${service_name}/listing-*.json`
81
81
  - Both offerings and listings are defined in the same service directory under the provider
82
82
 
83
+ #### Multiple Listings Per Service
84
+ When a single service offering has multiple listings (e.g., different pricing tiers, different marketplaces), the filename becomes significant:
85
+
86
+ - **Filename as identifier**: If the `name` field is not provided in the listing file, the filename (without extension) is automatically used as the listing name
87
+ - **Example**: `listing-premium.json`, `listing-basic.json`, `listing-enterprise.json` for different tiers
88
+ - **Best practice**: Use descriptive filenames that indicate the listing variant, or explicitly set the `name` field in each file
89
+
83
90
  ### 7. External Files (Documentation, Code Examples, etc.)
84
91
  - External files like code examples, documentation, images can be placed anywhere in the directory structure
85
92
  - They are referenced by **relative paths** from the referencing file
@@ -181,10 +188,11 @@ data/
181
188
  │ └── services/
182
189
  │ ├── gpt-4/ # Service: "gpt-4"
183
190
  │ │ ├── service.json # name = "gpt-4"
184
- │ │ └── listing-svcreseller.json # seller_name = "svcreseller"
191
+ │ │ ├── listing-premium.json # name = "listing-premium" (or defaults to filename)
192
+ │ │ └── listing-basic.json # name = "listing-basic" (multiple listings for one service)
185
193
  │ └── gpt-3.5-turbo/ # Service: "gpt-3.5-turbo"
186
194
  │ ├── service.json # name = "gpt-3.5-turbo"
187
- │ └── listing-svcreseller.json
195
+ │ └── listing-svcreseller.json # Single listing
188
196
  └── anthropic/ # Provider: "anthropic"
189
197
  ├── provider.json # name = "anthropic"
190
198
  └── services/
@@ -194,6 +194,7 @@ Listing files define how a seller presents/sells a service (downstream/marketpla
194
194
  | Field | Type | Description |
195
195
  |-------|------|-------------|
196
196
  | `schema` | string | Must be `"listing_v1"` |
197
+ | `name` | string | Listing identifier (defaults to filename without extension if not provided) |
197
198
  | `seller_name` | string | Seller identifier (references seller file) |
198
199
  | `listing_status` | string | Listing status (see Status Values) |
199
200
 
@@ -209,6 +210,15 @@ Listing files define how a seller presents/sells a service (downstream/marketpla
209
210
  | `documents` | array | Documentation files |
210
211
  | `tags` | array | Search/filter tags |
211
212
 
213
+ ### Listing Name Field
214
+
215
+ The `name` field identifies the listing and is especially important when multiple listings exist for a single service offering:
216
+
217
+ - **Automatic naming**: If the `name` field is not provided, the SDK automatically uses the filename (without extension) as the listing name
218
+ - **Multiple listings**: When you have multiple listings for one service (e.g., different tiers or marketplaces), use descriptive filenames
219
+ - **Example**: A file named `listing-premium.json` will automatically get `name = "listing-premium"` if the field is omitted
220
+ - **Best practice**: Use explicit `name` fields for clarity, or use descriptive filenames that will serve as meaningful listing identifiers
221
+
212
222
  ### listing_status Values
213
223
 
214
224
  - `unknown` - Status not yet determined
@@ -223,6 +233,7 @@ Listing files define how a seller presents/sells a service (downstream/marketpla
223
233
 
224
234
  ```toml
225
235
  schema = "listing_v1"
236
+ name = "listing-premium"
226
237
  seller_name = "svcreseller"
227
238
  service_name = "gpt-4"
228
239
  listing_status = "in_service"
@@ -147,9 +147,17 @@ unitysvc_services publish sellers
147
147
  ### Step 9: Verify Your Published Data
148
148
 
149
149
  ```bash
150
+ # Query with default fields
150
151
  unitysvc_services query providers
151
152
  unitysvc_services query offerings
152
153
  unitysvc_services query listings
154
+
155
+ # Query with custom fields - show only specific columns
156
+ unitysvc_services query providers --fields id,name,contact_email
157
+ unitysvc_services query listings --fields id,service_name,listing_type,status
158
+
159
+ # Query as JSON for programmatic use
160
+ unitysvc_services query offerings --format json
153
161
  ```
154
162
 
155
163
  ## Next Steps
@@ -102,9 +102,14 @@ unitysvc_services publish --data-path ./data
102
102
  #### 7. Verify on Platform
103
103
 
104
104
  ```bash
105
+ # Query with default fields
105
106
  unitysvc_services query providers
106
107
  unitysvc_services query offerings
107
108
  unitysvc_services query listings
109
+
110
+ # Or query with custom fields for focused output
111
+ unitysvc_services query providers --fields id,name,status
112
+ unitysvc_services query listings --fields id,service_name,listing_type,status
108
113
  ```
109
114
 
110
115
  ### Version Control Integration
@@ -269,7 +274,11 @@ unitysvc_services publish
269
274
  #### 8. Verify
270
275
 
271
276
  ```bash
277
+ # Query with default fields
272
278
  unitysvc_services query offerings
279
+
280
+ # Or query with custom fields
281
+ unitysvc_services query offerings --fields id,service_name,status
273
282
  ```
274
283
 
275
284
  ### Automation with CI/CD
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "unitysvc-services"
3
- version = "0.2.3"
3
+ version = "0.2.5"
4
4
  description = "SDK for digital service providers on UnitySVC"
5
5
  readme = "README.md"
6
6
  authors = [{ name = "Bo Peng", email = "bo.peng@unitysvc.com" }]
@@ -3,12 +3,7 @@ from typing import Any
3
3
 
4
4
  from pydantic import BaseModel, ConfigDict, Field
5
5
 
6
- from unitysvc_services.models.base import (
7
- AccessInterface,
8
- Document,
9
- ListingStatusEnum,
10
- Pricing,
11
- )
6
+ from unitysvc_services.models.base import AccessInterface, Document, ListingStatusEnum, Pricing
12
7
 
13
8
 
14
9
  class ListingV1(BaseModel):
@@ -32,6 +27,10 @@ class ListingV1(BaseModel):
32
27
 
33
28
  seller_name: str | None = Field(default=None, description="Name of the seller offering this service listing")
34
29
 
30
+ name: str = Field(
31
+ max_length=255,
32
+ description="Name identifier for the service listing, default to filename",
33
+ )
35
34
  # unique name for each provider, usually following upstream naming convention
36
35
  # status of the service, public, deprecated etc
37
36
  listing_status: ListingStatusEnum = Field(
@@ -106,6 +106,11 @@ class ServiceDataPublisher:
106
106
 
107
107
  # Resolve file references and include content
108
108
  base_path = data_file.parent
109
+ data = convert_convenience_fields_to_documents(
110
+ data, base_path, logo_field="logo", terms_field="terms_of_service"
111
+ )
112
+
113
+ # Resolve file references and include content
109
114
  data_with_content = self.resolve_file_references(data, base_path)
110
115
 
111
116
  # Extract provider_name from directory structure
@@ -154,6 +159,10 @@ class ServiceDataPublisher:
154
159
  # Load the listing data file
155
160
  data = self.load_data_file(data_file)
156
161
 
162
+ # If name is not provided, use filename (without extension)
163
+ if "name" not in data or not data.get("name"):
164
+ data["name"] = data_file.stem
165
+
157
166
  # Resolve file references and include content
158
167
  base_path = data_file.parent
159
168
  data_with_content = self.resolve_file_references(data, base_path)
@@ -39,45 +39,53 @@ class ServiceDataQuery:
39
39
  timeout=30.0,
40
40
  )
41
41
 
42
- def list_service_offerings(self) -> list[dict[str, Any]]:
43
- """List all service offerings from the backend."""
44
- response = self.client.get(f"{self.base_url}/publish/offerings")
45
- response.raise_for_status()
46
- result = response.json()
47
- return result.get("data", result) if isinstance(result, dict) else result
42
+ def list_service_offerings(self, skip: int = 0, limit: int = 100) -> list[dict[str, Any]]:
43
+ """List all service offerings from the backend.
48
44
 
49
- def list_service_listings(self) -> list[dict[str, Any]]:
50
- """List all service listings from the backend."""
51
- response = self.client.get(f"{self.base_url}/publish/listings")
45
+ Args:
46
+ skip: Number of records to skip (for pagination)
47
+ limit: Maximum number of records to return
48
+ """
49
+ response = self.client.get(f"{self.base_url}/publish/offerings", params={"skip": skip, "limit": limit})
52
50
  response.raise_for_status()
53
51
  result = response.json()
54
52
  return result.get("data", result) if isinstance(result, dict) else result
55
53
 
56
- def list_providers(self) -> list[dict[str, Any]]:
57
- """List all providers from the backend."""
58
- response = self.client.get(f"{self.base_url}/publish/providers")
54
+ def list_service_listings(self, skip: int = 0, limit: int = 100) -> list[dict[str, Any]]:
55
+ """List all service listings from the backend.
56
+
57
+ Args:
58
+ skip: Number of records to skip (for pagination)
59
+ limit: Maximum number of records to return
60
+ """
61
+ response = self.client.get(f"{self.base_url}/publish/listings", params={"skip": skip, "limit": limit})
59
62
  response.raise_for_status()
60
63
  result = response.json()
61
64
  return result.get("data", result) if isinstance(result, dict) else result
62
65
 
63
- def list_sellers(self) -> list[dict[str, Any]]:
64
- """List all sellers from the backend."""
65
- response = self.client.get(f"{self.base_url}/publish/sellers")
66
+ def list_providers(self, skip: int = 0, limit: int = 100) -> list[dict[str, Any]]:
67
+ """List all providers from the backend.
68
+
69
+ Args:
70
+ skip: Number of records to skip (for pagination)
71
+ limit: Maximum number of records to return
72
+ """
73
+ response = self.client.get(f"{self.base_url}/publish/providers", params={"skip": skip, "limit": limit})
66
74
  response.raise_for_status()
67
75
  result = response.json()
68
76
  return result.get("data", result) if isinstance(result, dict) else result
69
77
 
70
- def list_access_interfaces(self) -> dict[str, Any]:
71
- """List all access interfaces from the backend (private endpoint)."""
72
- response = self.client.get(f"{self.base_url}/private/interfaces")
73
- response.raise_for_status()
74
- return response.json()
78
+ def list_sellers(self, skip: int = 0, limit: int = 100) -> list[dict[str, Any]]:
79
+ """List all sellers from the backend.
75
80
 
76
- def list_documents(self) -> dict[str, Any]:
77
- """List all documents from the backend (private endpoint)."""
78
- response = self.client.get(f"{self.base_url}/private/documents")
81
+ Args:
82
+ skip: Number of records to skip (for pagination)
83
+ limit: Maximum number of records to return
84
+ """
85
+ response = self.client.get(f"{self.base_url}/publish/sellers", params={"skip": skip, "limit": limit})
79
86
  response.raise_for_status()
80
- return response.json()
87
+ result = response.json()
88
+ return result.get("data", result) if isinstance(result, dict) else result
81
89
 
82
90
  def close(self):
83
91
  """Close the HTTP client."""
@@ -111,6 +119,16 @@ def query_sellers(
111
119
  "created_at, updated_at, status"
112
120
  ),
113
121
  ),
122
+ skip: int = typer.Option(
123
+ 0,
124
+ "--skip",
125
+ help="Number of records to skip (for pagination)",
126
+ ),
127
+ limit: int = typer.Option(
128
+ 100,
129
+ "--limit",
130
+ help="Maximum number of records to return (default: 100)",
131
+ ),
114
132
  ):
115
133
  """Query all sellers from the backend.
116
134
 
@@ -121,6 +139,12 @@ def query_sellers(
121
139
  # Show only specific fields
122
140
  unitysvc_services query sellers --fields id,name,contact_email
123
141
 
142
+ # Retrieve more than 100 records
143
+ unitysvc_services query sellers --limit 500
144
+
145
+ # Pagination: skip first 100, get next 100
146
+ unitysvc_services query sellers --skip 100 --limit 100
147
+
124
148
  # Show all available fields
125
149
  unitysvc_services query sellers --fields \\
126
150
  id,name,display_name,seller_type,contact_email,homepage,created_at,updated_at
@@ -158,7 +182,7 @@ def query_sellers(
158
182
 
159
183
  try:
160
184
  with ServiceDataQuery() as query:
161
- sellers = query.list_sellers()
185
+ sellers = query.list_sellers(skip=skip, limit=limit)
162
186
 
163
187
  if format == "json":
164
188
  # For JSON, filter fields if not all are requested
@@ -255,6 +279,16 @@ def query_providers(
255
279
  "homepage, description, status, created_at, updated_at"
256
280
  ),
257
281
  ),
282
+ skip: int = typer.Option(
283
+ 0,
284
+ "--skip",
285
+ help="Number of records to skip (for pagination)",
286
+ ),
287
+ limit: int = typer.Option(
288
+ 100,
289
+ "--limit",
290
+ help="Maximum number of records to return (default: 100)",
291
+ ),
258
292
  ):
259
293
  """Query all providers from the backend.
260
294
 
@@ -262,6 +296,12 @@ def query_providers(
262
296
  # Use default fields
263
297
  unitysvc_services query providers
264
298
 
299
+ # Retrieve more than 100 records
300
+ unitysvc_services query providers --limit 500
301
+
302
+ # Pagination: skip first 100, get next 100
303
+ unitysvc_services query providers --skip 100 --limit 100
304
+
265
305
  # Show only specific fields
266
306
  unitysvc_services query providers --fields id,name,contact_email
267
307
 
@@ -298,7 +338,7 @@ def query_providers(
298
338
 
299
339
  try:
300
340
  with ServiceDataQuery() as query:
301
- providers = query.list_providers()
341
+ providers = query.list_providers(skip=skip, limit=limit)
302
342
 
303
343
  if format == "json":
304
344
  # For JSON, filter fields if not all are requested
@@ -389,6 +429,16 @@ def query_offerings(
389
429
  "service_type, provider_name"
390
430
  ),
391
431
  ),
432
+ skip: int = typer.Option(
433
+ 0,
434
+ "--skip",
435
+ help="Number of records to skip (for pagination)",
436
+ ),
437
+ limit: int = typer.Option(
438
+ 100,
439
+ "--limit",
440
+ help="Maximum number of records to return (default: 100)",
441
+ ),
392
442
  ):
393
443
  """Query all service offerings from UnitySVC backend.
394
444
 
@@ -399,6 +449,12 @@ def query_offerings(
399
449
  # Show only specific fields
400
450
  unitysvc_services query offerings --fields id,service_name,status
401
451
 
452
+ # Retrieve more than 100 records
453
+ unitysvc_services query offerings --limit 500
454
+
455
+ # Pagination: skip first 100, get next 100
456
+ unitysvc_services query offerings --skip 100 --limit 100
457
+
402
458
  # Show all available fields
403
459
  unitysvc_services query offerings --fields \\
404
460
  id,service_name,service_type,provider_name,status,price,definition_id,provider_id
@@ -430,7 +486,7 @@ def query_offerings(
430
486
 
431
487
  try:
432
488
  with ServiceDataQuery() as query:
433
- offerings = query.list_service_offerings()
489
+ offerings = query.list_service_offerings(skip=skip, limit=limit)
434
490
 
435
491
  if format == "json":
436
492
  # For JSON, filter fields if not all are requested
@@ -489,11 +545,21 @@ def query_listings(
489
545
  "--fields",
490
546
  help=(
491
547
  "Comma-separated list of fields to display. Available fields: "
492
- "id, offering_id, seller_id, status, created_at, updated_at, "
548
+ "id, offering_id, offering_status, seller_id, status, created_at, updated_at, "
493
549
  "parameters_schema, parameters_ui_schema, tags, service_name, "
494
550
  "service_type, provider_name, seller_name, listing_type"
495
551
  ),
496
552
  ),
553
+ skip: int = typer.Option(
554
+ 0,
555
+ "--skip",
556
+ help="Number of records to skip (for pagination)",
557
+ ),
558
+ limit: int = typer.Option(
559
+ 100,
560
+ "--limit",
561
+ help="Maximum number of records to return (default: 100)",
562
+ ),
497
563
  ):
498
564
  """Query all service listings from UnitySVC backend.
499
565
 
@@ -504,6 +570,12 @@ def query_listings(
504
570
  # Show only specific fields
505
571
  unitysvc_services query listings --fields id,service_name,status
506
572
 
573
+ # Retrieve more than 100 records
574
+ unitysvc_services query listings --limit 500
575
+
576
+ # Pagination: skip first 100, get next 100
577
+ unitysvc_services query listings --skip 100 --limit 100
578
+
507
579
  # Show all available fields
508
580
  unitysvc_services query listings --fields \\
509
581
  id,service_name,service_type,seller_name,listing_type,status,provider_name
@@ -515,6 +587,7 @@ def query_listings(
515
587
  allowed_fields = {
516
588
  "id",
517
589
  "offering_id",
590
+ "offering_status",
518
591
  "seller_id",
519
592
  "status",
520
593
  "created_at",
@@ -541,7 +614,7 @@ def query_listings(
541
614
 
542
615
  try:
543
616
  with ServiceDataQuery() as query:
544
- listings = query.list_service_listings()
617
+ listings = query.list_service_listings(skip=skip, limit=limit)
545
618
 
546
619
  if format == "json":
547
620
  # For JSON, filter fields if not all are requested
@@ -583,232 +656,3 @@ def query_listings(
583
656
  except Exception as e:
584
657
  console.print(f"[red]✗[/red] Failed to query service listings: {e}", style="bold red")
585
658
  raise typer.Exit(code=1)
586
-
587
-
588
- @app.command("interfaces")
589
- def query_interfaces(
590
- format: str = typer.Option(
591
- "table",
592
- "--format",
593
- "-f",
594
- help="Output format: table, json",
595
- ),
596
- fields: str = typer.Option(
597
- "id,name,context_type,access_method,is_active",
598
- "--fields",
599
- help=(
600
- "Comma-separated list of fields to display. Available fields: "
601
- "id, entity_id, context_type, access_method, api_endpoint, name, "
602
- "description, request_transformer, rate_limits, constraint, "
603
- "is_active, is_primary, sort_order, created_at, updated_at"
604
- ),
605
- ),
606
- ):
607
- """Query all access interfaces from UnitySVC backend (private endpoint).
608
-
609
- Examples:
610
- # Use default fields
611
- unitysvc_services query interfaces
612
-
613
- # Show only specific fields
614
- unitysvc_services query interfaces --fields id,name,access_method
615
-
616
- # Show all available fields
617
- unitysvc_services query interfaces --fields \\
618
- id,name,context_type,access_method,entity_id,is_active,is_primary
619
- """
620
- # Parse fields list
621
- field_list = [f.strip() for f in fields.split(",")]
622
-
623
- # Define allowed fields from AccessInterfacePublic model
624
- allowed_fields = {
625
- "id",
626
- "entity_id",
627
- "context_type",
628
- "access_method",
629
- "api_endpoint",
630
- "name",
631
- "description",
632
- "request_transformer",
633
- "rate_limits",
634
- "constraint",
635
- "is_active",
636
- "is_primary",
637
- "sort_order",
638
- "created_at",
639
- "updated_at",
640
- }
641
-
642
- # Validate fields
643
- invalid_fields = [f for f in field_list if f not in allowed_fields]
644
- if invalid_fields:
645
- console.print(
646
- f"[red]Error:[/red] Invalid field(s): {', '.join(invalid_fields)}",
647
- style="bold red",
648
- )
649
- console.print(f"[yellow]Available fields:[/yellow] {', '.join(sorted(allowed_fields))}")
650
- raise typer.Exit(code=1)
651
-
652
- try:
653
- with ServiceDataQuery() as query:
654
- data = query.list_access_interfaces()
655
-
656
- if format == "json":
657
- # For JSON, filter fields if not all are requested
658
- interfaces = data.get("data", [])
659
- if set(field_list) != allowed_fields:
660
- filtered_interfaces = [
661
- {k: v for k, v in interface.items() if k in field_list} for interface in interfaces
662
- ]
663
- console.print(json.dumps({"data": filtered_interfaces, "count": data.get("count", 0)}, indent=2))
664
- else:
665
- console.print(json.dumps(data, indent=2))
666
- else:
667
- interfaces = data.get("data", [])
668
- if not interfaces:
669
- console.print("[yellow]No access interfaces found.[/yellow]")
670
- else:
671
- table = Table(title="Access Interfaces")
672
-
673
- # Add columns dynamically based on selected fields
674
- for field in field_list:
675
- # Capitalize and format field names for display
676
- column_name = field.replace("_", " ").title()
677
- table.add_column(column_name)
678
-
679
- # Add rows
680
- for interface in interfaces:
681
- row = []
682
- for field in field_list:
683
- value = interface.get(field)
684
- if value is None:
685
- row.append("N/A")
686
- elif isinstance(value, dict | list):
687
- row.append(str(value)[:50]) # Truncate complex types
688
- else:
689
- row.append(str(value))
690
- table.add_row(*row)
691
-
692
- console.print(table)
693
- console.print(f"\n[green]Total:[/green] {data.get('count', 0)} access interface(s)")
694
- except ValueError as e:
695
- console.print(f"[red]✗[/red] {e}", style="bold red")
696
- raise typer.Exit(code=1)
697
- except Exception as e:
698
- console.print(f"[red]✗[/red] Failed to query access interfaces: {e}", style="bold red")
699
- raise typer.Exit(code=1)
700
-
701
-
702
- @app.command("documents")
703
- def query_documents(
704
- format: str = typer.Option(
705
- "table",
706
- "--format",
707
- "-f",
708
- help="Output format: table, json",
709
- ),
710
- fields: str = typer.Option(
711
- "id,title,category,mime_type,context_type,is_public",
712
- "--fields",
713
- help=(
714
- "Comma-separated list of fields to display. Available fields: "
715
- "id, entity_id, context_type, title, description, mime_type, "
716
- "version, category, meta, sort_order, is_active, is_public, "
717
- "external_url, object_key, filename, filesize, created_at, updated_at"
718
- ),
719
- ),
720
- ):
721
- """Query all documents from UnitySVC backend (private endpoint).
722
-
723
- Examples:
724
- # Use default fields
725
- unitysvc_services query documents
726
-
727
- # Show only specific fields
728
- unitysvc_services query documents --fields id,title,category
729
-
730
- # Show all available fields
731
- unitysvc_services query documents --fields \\
732
- id,title,category,mime_type,context_type,is_public,filename,filesize
733
- """
734
- # Parse fields list
735
- field_list = [f.strip() for f in fields.split(",")]
736
-
737
- # Define allowed fields from DocumentPublic model
738
- allowed_fields = {
739
- "id",
740
- "entity_id",
741
- "context_type",
742
- "title",
743
- "description",
744
- "mime_type",
745
- "version",
746
- "category",
747
- "meta",
748
- "sort_order",
749
- "is_active",
750
- "is_public",
751
- "external_url",
752
- "object_key",
753
- "filename",
754
- "filesize",
755
- "created_at",
756
- "updated_at",
757
- }
758
-
759
- # Validate fields
760
- invalid_fields = [f for f in field_list if f not in allowed_fields]
761
- if invalid_fields:
762
- console.print(
763
- f"[red]Error:[/red] Invalid field(s): {', '.join(invalid_fields)}",
764
- style="bold red",
765
- )
766
- console.print(f"[yellow]Available fields:[/yellow] {', '.join(sorted(allowed_fields))}")
767
- raise typer.Exit(code=1)
768
-
769
- try:
770
- with ServiceDataQuery() as query:
771
- data = query.list_documents()
772
-
773
- if format == "json":
774
- # For JSON, filter fields if not all are requested
775
- documents = data.get("data", [])
776
- if set(field_list) != allowed_fields:
777
- filtered_documents = [{k: v for k, v in doc.items() if k in field_list} for doc in documents]
778
- console.print(json.dumps({"data": filtered_documents, "count": data.get("count", 0)}, indent=2))
779
- else:
780
- console.print(json.dumps(data, indent=2))
781
- else:
782
- documents = data.get("data", [])
783
- if not documents:
784
- console.print("[yellow]No documents found.[/yellow]")
785
- else:
786
- table = Table(title="Documents")
787
-
788
- # Add columns dynamically based on selected fields
789
- for field in field_list:
790
- # Capitalize and format field names for display
791
- column_name = field.replace("_", " ").title()
792
- table.add_column(column_name)
793
-
794
- # Add rows
795
- for doc in documents:
796
- row = []
797
- for field in field_list:
798
- value = doc.get(field)
799
- if value is None:
800
- row.append("N/A")
801
- elif isinstance(value, dict | list):
802
- row.append(str(value)[:50]) # Truncate complex types
803
- else:
804
- row.append(str(value))
805
- table.add_row(*row)
806
-
807
- console.print(table)
808
- console.print(f"\n[green]Total:[/green] {data.get('count', 0)} document(s)")
809
- except ValueError as e:
810
- console.print(f"[red]✗[/red] {e}", style="bold red")
811
- raise typer.Exit(code=1)
812
- except Exception as e:
813
- console.print(f"[red]✗[/red] Failed to query documents: {e}", style="bold red")
814
- raise typer.Exit(code=1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unitysvc-services
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: SDK for digital service providers on UnitySVC
5
5
  Author-email: Bo Peng <bo.peng@unitysvc.com>
6
6
  Maintainer-email: Bo Peng <bo.peng@unitysvc.com>
@@ -87,8 +87,11 @@ unitysvc_services publish
87
87
  # Or publish specific types only
88
88
  unitysvc_services publish providers
89
89
 
90
- # Verify
90
+ # Verify with default fields
91
91
  unitysvc_services query offerings
92
+
93
+ # Query with custom fields
94
+ unitysvc_services query providers --fields id,name,contact_email
92
95
  ```
93
96
 
94
97
  ## Key Features