@tdk-landscape/tdk-cli-core 1.3.32 → 1.3.36
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.
- package/discovery/discovery_orchestrator.star +4 -4
- package/discovery/manifest/loading.star +9 -5
- package/discovery/manifest/normalize.star +3 -3
- package/discovery/manifest/validation.star +1 -1
- package/discovery/validation.star +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +120 -6
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/help.js +1 -1
- package/dist/commands/help.js.map +1 -1
- package/dist/commands/project.d.ts.map +1 -1
- package/dist/commands/project.js +27 -23
- package/dist/commands/project.js.map +1 -1
- package/dist/commands/resource.js +1 -1
- package/dist/commands/resource.js.map +1 -1
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +2 -48
- package/dist/commands/up.js.map +1 -1
- package/dist/generator/template-engine.d.ts +1 -1
- package/dist/generator/template-engine.d.ts.map +1 -1
- package/dist/generator/template-engine.js +96 -44
- package/dist/generator/template-engine.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/types/index.d.ts +20 -7
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +11 -0
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/resource-features.d.ts +1 -1
- package/dist/utils/resource-features.js +1 -1
- package/dist/utils/service-urls.d.ts +30 -0
- package/dist/utils/service-urls.d.ts.map +1 -0
- package/dist/utils/service-urls.js +93 -0
- package/dist/utils/service-urls.js.map +1 -0
- package/dist/utils/stack-features.d.ts +4 -4
- package/dist/utils/stack-features.d.ts.map +1 -1
- package/dist/utils/stack-features.js +1 -1
- package/dist/utils/stack-features.js.map +1 -1
- package/engine/REFACTORING_MANIFEST_SYSTEM.md +1 -1
- package/engine/lifecycle/orchestrator.star +4 -3
- package/engine/schemas/service-schema.json +5 -5
- package/engine/topologies/platform/docker/compose/compose.star +44 -24
- package/engine/topologies/platform/docker/constants.star +4 -0
- package/engine/topologies/platform/docker/generators/golden_docker_generator_v2.star +1 -0
- package/engine/topologies/platform/docker/layers/l4_runtime_layers.star +10 -6
- package/engine/topologies/platform/docker/networking/api_path_constants.star +30 -0
- package/engine/topologies/platform/docker/networking/traefik.star +2 -2
- package/engine/topologies/platform/net/AGENTS.md +64 -0
- package/engine/topologies/platform/security/AGENTS.md +49 -0
- package/engine/topologies/platform/state/AGENTS.md +64 -0
- package/engine/topologies/tilt/config/profiles.star +16 -2
- package/engine/topologies/tilt/generators/typescript/frontend_tsconfig.star +21 -9
- package/engine/topologies/tilt/generators/vite/backend.star +1 -1
- package/engine/topologies/tilt/generators/vite/frontend.star +2 -1
- package/engine/topologies/tilt/generators/vite/helpers.star +1 -1
- package/engine/topologies/tilt/manifest/constants.star +1 -1
- package/engine/topologies/tilt/manifest/mapper.star +2 -2
- package/engine/topologies/tilt/manifest/parser.star +2 -2
- package/engine/topologies/tilt/manifest/schema.star +2 -2
- package/engine/topologies/tilt/manifest/tests/test_loader_parser.star +3 -3
- package/engine/topologies/tilt/manifest/tests/test_validator.star +2 -2
- package/engine/topologies/tilt/manifest/validator.star +7 -7
- package/engine/topologies/tilt/resources/orchestrator/generators/env.star +3 -2
- package/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +3 -2
- package/package.json +1 -1
- package/templates/Tiltfile.hbs +16 -1
- package/templates/spec.master.hbs +11 -4
- package/engine/schemas/manifest-schema.json +0 -301
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# AGENTS.md - Security & Secrets
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Secrets management, Infisical integration, and security configuration.
|
|
6
|
+
|
|
7
|
+
## Key Files
|
|
8
|
+
|
|
9
|
+
### Secrets Management
|
|
10
|
+
- **`infisical.star`** - Infisical secrets provider integration
|
|
11
|
+
- **`secrets.star`** - Generic secrets handling
|
|
12
|
+
- **`encryption.star`** - Encryption utilities
|
|
13
|
+
|
|
14
|
+
### Configuration
|
|
15
|
+
- **`tokens.star`** - Token generation and validation
|
|
16
|
+
- **`keys.star`** - Key management
|
|
17
|
+
|
|
18
|
+
## Common Tasks
|
|
19
|
+
|
|
20
|
+
### Load secrets from Infisical
|
|
21
|
+
```starlark
|
|
22
|
+
load("./infisical.star", "Infisical")
|
|
23
|
+
secrets = Infisical.load_secrets(resource_name, environment)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Get database credentials
|
|
27
|
+
```starlark
|
|
28
|
+
load("./infisical.star", "Infisical")
|
|
29
|
+
db_url = Infisical.get_database_url(resource_name)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Integration
|
|
33
|
+
|
|
34
|
+
- Called by `resources/` when setting up service environment
|
|
35
|
+
- Used in Docker Compose for injecting secrets
|
|
36
|
+
- Part of service startup chain
|
|
37
|
+
|
|
38
|
+
## Local Development
|
|
39
|
+
|
|
40
|
+
Without Infisical, falls back to:
|
|
41
|
+
- Environment variables
|
|
42
|
+
- Default values in `spec.master`
|
|
43
|
+
|
|
44
|
+
## Security Notes
|
|
45
|
+
|
|
46
|
+
- Never commit real secrets
|
|
47
|
+
- Use Infisical for production
|
|
48
|
+
- Local development uses safe defaults
|
|
49
|
+
- Secrets injected at runtime, not in images
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# AGENTS.md - Database & State Management
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
PostgreSQL database virtualization, per-service database provisioning, and state management.
|
|
6
|
+
|
|
7
|
+
## Key Files
|
|
8
|
+
|
|
9
|
+
### Database Provisioning
|
|
10
|
+
- **`relational.star`** - Main database provisioning logic
|
|
11
|
+
- **`compose.star`** - Docker Compose entries for databases
|
|
12
|
+
|
|
13
|
+
### Prisma Integration
|
|
14
|
+
- **`prisma/migrate_script.star`** - Migration script generation
|
|
15
|
+
- **`prisma/db_readiness.star`** - Database readiness checks
|
|
16
|
+
- **`prisma/prisma_build.star`** - Prisma in Docker builds
|
|
17
|
+
- **`prisma/prisma_runtime.star`** - Prisma client in runtime
|
|
18
|
+
|
|
19
|
+
### Utilities
|
|
20
|
+
- **`utils.star`** - Database utilities
|
|
21
|
+
- **`constants.star`** - Database constants (ports, users)
|
|
22
|
+
|
|
23
|
+
## Common Tasks
|
|
24
|
+
|
|
25
|
+
### Provision database for service
|
|
26
|
+
```starlark
|
|
27
|
+
load("./relational.star", "provision_database")
|
|
28
|
+
compose_entry = provision_database("order-management-backend", "{project}_order")
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Get database URL
|
|
32
|
+
```starlark
|
|
33
|
+
load("./relational.star", "get_database_url")
|
|
34
|
+
url = get_database_url("order-management-backend")
|
|
35
|
+
# Returns: postgresql://postgres:postgres@order-management-backend-db:5432/{project}_order
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Wait for database
|
|
39
|
+
```starlark
|
|
40
|
+
load("./prisma/db_readiness.star", "wait_for_db")
|
|
41
|
+
script = wait_for_db(db_url, timeout=30)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Architecture
|
|
45
|
+
|
|
46
|
+
Each service with `databaseName` in manifest gets:
|
|
47
|
+
1. PostgreSQL container in Docker Compose
|
|
48
|
+
2. Volume for persistence
|
|
49
|
+
3. Readiness check before migrations
|
|
50
|
+
4. Dedicated port mapping (avoids conflicts)
|
|
51
|
+
|
|
52
|
+
## Integration
|
|
53
|
+
|
|
54
|
+
- Called by `resources/deps.star` - when setting up service dependencies
|
|
55
|
+
- Used by `platform/docker/` - for Docker Compose generation
|
|
56
|
+
- Part of service resource dependencies chain
|
|
57
|
+
|
|
58
|
+
## Database Naming
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
{project}_{domain} // e.g., {project}_order, {project}_user
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Each domain gets one database shared by its services (backend, migrator, etc).
|
|
@@ -321,13 +321,27 @@ def apply_focus_filter(cfg):
|
|
|
321
321
|
# Logic toggles (e.g. "golden-image", "database-management") are excluded since they're config flags, not resources.
|
|
322
322
|
# Infrastructure resources (postgres, nats, traefik, etc.) are loaded via Infra.load_all()
|
|
323
323
|
# and excluded here since they may not be available in all projects.
|
|
324
|
-
# Only include resources that exist as discovered services
|
|
324
|
+
# Only include resources that exist as discovered services.
|
|
325
|
+
#
|
|
326
|
+
# NOTE: resource_aliases (from get_resource_aliases_ref()) only maps top-level
|
|
327
|
+
# STACK/domain names (e.g. "app", "billing") to a path - it does not contain an
|
|
328
|
+
# entry per concrete resource (e.g. "dashboard-api", "checkout-app"). _get_resources_for_domain()
|
|
329
|
+
# already expanded stack names into concrete resource names above (all_needed), so those
|
|
330
|
+
# concrete names must be recognized here too, or they get silently dropped and their
|
|
331
|
+
# services never start. Build that set directly from the discovered service resources.
|
|
325
332
|
resource_aliases = get_resource_aliases_ref()
|
|
333
|
+
known_service_resource_names = {}
|
|
334
|
+
for _svc in get_app_resources_ref():
|
|
335
|
+
for _res in _svc.get("resources", []):
|
|
336
|
+
_res_name = _res.get("name", "")
|
|
337
|
+
if _res_name:
|
|
338
|
+
known_service_resource_names[_res_name] = True
|
|
339
|
+
known_service_resource_names[_res_name + "-yaml"] = True
|
|
326
340
|
resource_only_needed = []
|
|
327
341
|
for r in all_needed:
|
|
328
342
|
if r in logic_toggles:
|
|
329
343
|
continue
|
|
330
|
-
if r not in resource_aliases:
|
|
344
|
+
if r not in resource_aliases and r not in known_service_resource_names:
|
|
331
345
|
continue
|
|
332
346
|
resource_only_needed.append(r)
|
|
333
347
|
|
|
@@ -38,12 +38,17 @@ def generate_frontend_tsconfig(resource_path, write_fn, internal_deps=None, is_d
|
|
|
38
38
|
is_docker,
|
|
39
39
|
internal_deps != None
|
|
40
40
|
))
|
|
41
|
-
#
|
|
41
|
+
# Local dev tsconfig lives in .autogenerated/, so "src" etc. are one level up (../src).
|
|
42
|
+
# The Docker-variant tsconfig is written to the same .autogenerated/ path on disk, but the
|
|
43
|
+
# Dockerfile COPYs it to the image's app root as ./tsconfig.json (sibling of ./src, not
|
|
44
|
+
# nested under .autogenerated/) - so its own paths must be relative to that root instead,
|
|
45
|
+
# or tsc reports "No inputs were found" because it looks one directory too high.
|
|
46
|
+
src_prefix = "./" if is_docker else "../"
|
|
42
47
|
paths = {
|
|
43
|
-
"@/*": ["
|
|
48
|
+
"@/*": [src_prefix + "src/*"],
|
|
44
49
|
"@/autogenerated/*": ["./.autogenerated/*"]
|
|
45
50
|
}
|
|
46
|
-
include_paths = ["
|
|
51
|
+
include_paths = [src_prefix + "src/**/*"]
|
|
47
52
|
|
|
48
53
|
# =============================================================================
|
|
49
54
|
# CRITICAL FIX: Only add path aliases for internal deps in LOCAL builds
|
|
@@ -81,16 +86,23 @@ def generate_frontend_tsconfig(resource_path, write_fn, internal_deps=None, is_d
|
|
|
81
86
|
"paths": paths,
|
|
82
87
|
"skipLibCheck": True,
|
|
83
88
|
"strict": True,
|
|
84
|
-
"
|
|
89
|
+
"esModuleInterop": True,
|
|
90
|
+
"allowSyntheticDefaultImports": True,
|
|
91
|
+
# "bun" (not "node"): matches backend_tsconfig.star - @types/bun is a direct
|
|
92
|
+
# devDependency so it's always linked at the top level under any linker mode
|
|
93
|
+
# (including Docker's isolated linker), while @types/node (when only pulled in
|
|
94
|
+
# transitively, e.g. via bun-types) isn't hoisted under the isolated linker and
|
|
95
|
+
# "types": ["node"] fails to resolve there even though it works locally.
|
|
96
|
+
"types": ["bun"],
|
|
85
97
|
},
|
|
86
98
|
"exclude": [
|
|
87
99
|
"node_modules",
|
|
88
100
|
"dist",
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
101
|
+
src_prefix + "__tests__/**/*",
|
|
102
|
+
src_prefix + "**/*.test.ts",
|
|
103
|
+
src_prefix + "**/tests/**/*",
|
|
104
|
+
src_prefix + "**/*.steps.ts",
|
|
105
|
+
src_prefix + "**/*.spec.ts"
|
|
94
106
|
],
|
|
95
107
|
"include": include_paths
|
|
96
108
|
}
|
|
@@ -45,7 +45,7 @@ def generate_backend(manifest, write_fn=None):
|
|
|
45
45
|
|
|
46
46
|
# 🔥 SMART DETECTION: Check if service uses vite-plugin-node for HMR
|
|
47
47
|
use_vite_node = manifest.get('useViteNode', False)
|
|
48
|
-
features = manifest.get('
|
|
48
|
+
features = manifest.get('featuresEnabled', [])
|
|
49
49
|
if 'vite-node' in features or 'vite-plugin-node' in features or 'hmr' in features:
|
|
50
50
|
use_vite_node = True
|
|
51
51
|
|
|
@@ -16,6 +16,7 @@ load('../../../../topologies/tilt/manifest/constants.star', 'GENERATED_CONFIG_FI
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
load('./templates.star', 'TEMPLATE_VITE_FRONTEND', 'TEMPLATE_VITE_FRONTEND_BUILD')
|
|
19
|
+
load('../../../platform/docker/networking/api_path_constants.star', 'get_frontend_base_path')
|
|
19
20
|
load('./helpers.star',
|
|
20
21
|
'build_header',
|
|
21
22
|
'generate_frontend_internal_aliases',
|
|
@@ -56,7 +57,7 @@ def generate_frontend(manifest, backend_manifest=None, write_fn=None):
|
|
|
56
57
|
stack = manifest.get('stack', 'app')
|
|
57
58
|
port = manifest.get('port', BASE_PORT_FRONTEND)
|
|
58
59
|
hmr_port = port + 1000 # HMR port is always port + 1000
|
|
59
|
-
base_path = manifest
|
|
60
|
+
base_path = get_frontend_base_path(manifest)
|
|
60
61
|
vite_base_path = _normalize_vite_base_path(base_path)
|
|
61
62
|
app_name = manifest.get('appName', 'unknown')
|
|
62
63
|
|
|
@@ -164,7 +164,7 @@ def generate_backend_path_aliases(resource_path, manifest):
|
|
|
164
164
|
# hand-edited features: ["ddd"] with no key at all is still blocked, but real
|
|
165
165
|
# entitlement is checked client-side by hasDddLicense() in extension-fetch.ts
|
|
166
166
|
# before the CLI ever writes "ddd" into a resource's features array.
|
|
167
|
-
ddd_enabled = 'ddd' in manifest.get('
|
|
167
|
+
ddd_enabled = 'ddd' in manifest.get('featuresEnabled', []) and os.environ.get('TDK_LICENSE_KEY', '') != ''
|
|
168
168
|
|
|
169
169
|
if ddd_enabled:
|
|
170
170
|
ddd_aliases = [
|
|
@@ -31,7 +31,7 @@ FIELD_MAPPINGS = {
|
|
|
31
31
|
'replicas': ['replicas', 'instances', 'count', 'spec.replicas', 'metadata.replicas'],
|
|
32
32
|
|
|
33
33
|
# Feature flags
|
|
34
|
-
'
|
|
34
|
+
'featuresEnabled': ['featuresEnabled', 'capabilities', 'spec.features', 'enabledFeatures', 'app.features'],
|
|
35
35
|
|
|
36
36
|
# Dependencies
|
|
37
37
|
'dependsOn': [
|
|
@@ -199,7 +199,7 @@ def _to_yaml_format(internal_manifest):
|
|
|
199
199
|
'port': internal_manifest.get('port', 4000),
|
|
200
200
|
'runtime': internal_manifest.get('runtime', 'bun'),
|
|
201
201
|
'replicas': internal_manifest.get('replicas', 1),
|
|
202
|
-
'
|
|
202
|
+
'featuresEnabled': internal_manifest.get('featuresEnabled', []),
|
|
203
203
|
'envVars': internal_manifest.get('envVars', {}),
|
|
204
204
|
'dependencies': {
|
|
205
205
|
'internal': internal_manifest.get('dependsOn', []),
|
|
@@ -90,7 +90,7 @@ def normalize(manifest, resource_path=""):
|
|
|
90
90
|
# Copy all existing fields
|
|
91
91
|
for key, value in manifest.items():
|
|
92
92
|
normalized[key] = value
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
# 1. Apply defaults for missing fields
|
|
95
95
|
for field, default_value in MANIFEST_DEFAULTS.items():
|
|
96
96
|
if field not in normalized or normalized[field] == None:
|
|
@@ -111,7 +111,7 @@ def normalize(manifest, resource_path=""):
|
|
|
111
111
|
if normalized.get('syncs') == None or normalized.get('syncs') == []:
|
|
112
112
|
normalized['syncs'] = _compute_syncs(
|
|
113
113
|
normalized['appType'],
|
|
114
|
-
normalized.get('
|
|
114
|
+
normalized.get('featuresEnabled', [])
|
|
115
115
|
)
|
|
116
116
|
|
|
117
117
|
# Compute backendName for frontends if missing
|
|
@@ -117,7 +117,7 @@ MANIFEST_SCHEMA = {
|
|
|
117
117
|
'description': 'Runtime environment',
|
|
118
118
|
'default': RUNTIME,
|
|
119
119
|
},
|
|
120
|
-
'
|
|
120
|
+
'featuresEnabled': {
|
|
121
121
|
'type': 'list',
|
|
122
122
|
'required': False,
|
|
123
123
|
'constraints': {
|
|
@@ -263,7 +263,7 @@ CROSS_FIELD_CONSTRAINTS = {
|
|
|
263
263
|
'message': 'Frontend resources must specify backendName and basePath',
|
|
264
264
|
},
|
|
265
265
|
'prisma_requires_database': {
|
|
266
|
-
'condition': {'field': '
|
|
266
|
+
'condition': {'field': 'featuresEnabled', 'contains': 'prisma'},
|
|
267
267
|
'requires': ['databaseName'],
|
|
268
268
|
'severity': 'warning',
|
|
269
269
|
'message': 'Resources using Prisma should specify databaseName',
|
|
@@ -281,7 +281,7 @@ def _test_manifest_merging():
|
|
|
281
281
|
'appName': 'test-service',
|
|
282
282
|
'appType': 'backend',
|
|
283
283
|
'port': 4000,
|
|
284
|
-
'
|
|
284
|
+
'featuresEnabled': ['nats'],
|
|
285
285
|
'envVars': {
|
|
286
286
|
'SHARED_VAR': 'base_value',
|
|
287
287
|
},
|
|
@@ -289,7 +289,7 @@ def _test_manifest_merging():
|
|
|
289
289
|
|
|
290
290
|
overlay = {
|
|
291
291
|
'port': 4001, # Override
|
|
292
|
-
'
|
|
292
|
+
'featuresEnabled': ['prisma'], # Override
|
|
293
293
|
'envVars': {
|
|
294
294
|
'SHARED_VAR': 'overlay_value', # Override
|
|
295
295
|
'NEW_VAR': 'new_value', # Add
|
|
@@ -300,7 +300,7 @@ def _test_manifest_merging():
|
|
|
300
300
|
|
|
301
301
|
assert_equal('test-service', merged['appName'], "Should preserve base appName")
|
|
302
302
|
assert_equal(4001, merged['port'], "Should overlay port")
|
|
303
|
-
assert_equal(['prisma'], merged['
|
|
303
|
+
assert_equal(['prisma'], merged['featuresEnabled'], "Should overlay features")
|
|
304
304
|
assert_equal('overlay_value', merged['envVars']['SHARED_VAR'], "Should overlay nested env var")
|
|
305
305
|
assert_equal('new_value', merged['envVars']['NEW_VAR'], "Should add new env var")
|
|
306
306
|
|
|
@@ -213,7 +213,7 @@ def _test_cross_field_validation():
|
|
|
213
213
|
'appType': 'backend',
|
|
214
214
|
'stack': 'user',
|
|
215
215
|
'port': 4001,
|
|
216
|
-
'
|
|
216
|
+
'featuresEnabled': ['prisma'],
|
|
217
217
|
# Missing databaseName
|
|
218
218
|
}
|
|
219
219
|
|
|
@@ -312,7 +312,7 @@ def _test_full_validation():
|
|
|
312
312
|
'port': 4000,
|
|
313
313
|
'replicas': 1,
|
|
314
314
|
'runtime': 'bun',
|
|
315
|
-
'
|
|
315
|
+
'featuresEnabled': ['nats', 'prisma'],
|
|
316
316
|
'databaseName': 'TDK_user',
|
|
317
317
|
'dependsOn': [],
|
|
318
318
|
'traefik': {
|
|
@@ -316,16 +316,16 @@ def _validate_values(manifest, context):
|
|
|
316
316
|
stats['rules_passed'] += 1
|
|
317
317
|
|
|
318
318
|
# Validate features length
|
|
319
|
-
if '
|
|
319
|
+
if 'featuresEnabled' in manifest:
|
|
320
320
|
stats['fields_checked'] += 1
|
|
321
|
-
features = manifest
|
|
322
|
-
|
|
321
|
+
features = manifest.get('featuresEnabled', [])
|
|
322
|
+
|
|
323
323
|
if len(features) > VALIDATION_THRESHOLDS['max_features']:
|
|
324
324
|
warnings.append(ManifestErrors.new(
|
|
325
325
|
message="Too many features ({}), consider splitting resource".format(len(features)),
|
|
326
326
|
category=ManifestErrors.CATEGORY['VALIDATION'],
|
|
327
327
|
severity=ManifestErrors.SEVERITY['WARNING'],
|
|
328
|
-
context={'field': '
|
|
328
|
+
context={'field': 'featuresEnabled', 'count': len(features), 'max': VALIDATION_THRESHOLDS['max_features']},
|
|
329
329
|
))
|
|
330
330
|
else:
|
|
331
331
|
stats['rules_passed'] += 1
|
|
@@ -374,16 +374,16 @@ def _validate_cross_field(manifest, context):
|
|
|
374
374
|
stats['rules_passed'] += 1
|
|
375
375
|
|
|
376
376
|
# Prisma requires databaseName
|
|
377
|
-
features = manifest.get('
|
|
377
|
+
features = manifest.get('featuresEnabled', [])
|
|
378
378
|
if 'prisma' in features:
|
|
379
379
|
stats['fields_checked'] += 1
|
|
380
|
-
|
|
380
|
+
|
|
381
381
|
if not manifest.get('databaseName'):
|
|
382
382
|
warnings.append(ManifestErrors.new(
|
|
383
383
|
message="Resource with 'prisma' feature should specify databaseName",
|
|
384
384
|
category=ManifestErrors.CATEGORY['VALIDATION'],
|
|
385
385
|
severity=ManifestErrors.SEVERITY['WARNING'],
|
|
386
|
-
context={'field': 'databaseName', '
|
|
386
|
+
context={'field': 'databaseName', 'featuresEnabled': features},
|
|
387
387
|
))
|
|
388
388
|
else:
|
|
389
389
|
stats['rules_passed'] += 1
|
|
@@ -14,6 +14,7 @@ OUTPUT = struct(AUTOGENERATED_FOLDER = ".autogenerated")
|
|
|
14
14
|
|
|
15
15
|
load("../../../../platform/docker/auth/auth.star", "AuthConfig")
|
|
16
16
|
load("../../../../platform/docker/networking/traefik_helpers.star", "get_api_path")
|
|
17
|
+
load("../../../../platform/docker/networking/api_path_constants.star", "get_frontend_base_path")
|
|
17
18
|
load("../../../../platform/docker/constants.star", "PlatformDockerConstants")
|
|
18
19
|
|
|
19
20
|
|
|
@@ -133,8 +134,8 @@ def _generate_params_env(manifest, backend_manifest=None, write_fn=None):
|
|
|
133
134
|
backend_name = manifest.get('backendName', stack + '-backend')
|
|
134
135
|
target_filename = '/' + OUTPUT.AUTOGENERATED_FOLDER + '/.env.frontend.autogenerated'
|
|
135
136
|
|
|
136
|
-
#
|
|
137
|
-
base_path = manifest
|
|
137
|
+
# Shared with the Traefik route and the Vite `base` -- see get_frontend_base_path.
|
|
138
|
+
base_path = get_frontend_base_path(manifest)
|
|
138
139
|
public_url = 'http://' + PlatformDockerConstants.LOCAL_DOMAIN + base_path
|
|
139
140
|
|
|
140
141
|
content = """# Generated by Tilt SDK - DO NOT EDIT
|
|
@@ -360,7 +360,8 @@ def _generate_all_configs_for_resource(
|
|
|
360
360
|
dockerfile_content = Docker.backend(
|
|
361
361
|
res_path=resource_path,
|
|
362
362
|
resource_name=resource_name,
|
|
363
|
-
use_golden=should_enable('golden-image')
|
|
363
|
+
use_golden=should_enable('golden-image'),
|
|
364
|
+
use_prisma='prisma' in manifest.get('featuresEnabled', [])
|
|
364
365
|
)
|
|
365
366
|
|
|
366
367
|
write_file(resource_path + "/" + OUTPUT.AUTOGENERATED_FOLDER + "/" + GENERATED_CONFIG_FILENAMES['dockerfile_app'], dockerfile_content)
|
|
@@ -404,7 +405,7 @@ def _generate_all_configs_for_resource(
|
|
|
404
405
|
TSConfig.frontend(resource_path, write_file, internal_deps=internal_deps_map, is_docker=False)
|
|
405
406
|
else:
|
|
406
407
|
prisma_path = resource_config.get('prisma_client_path', './node_modules/.prisma/client')
|
|
407
|
-
resource_features = manifest.get('
|
|
408
|
+
resource_features = manifest.get('featuresEnabled', [])
|
|
408
409
|
TSConfig.backend(resource_path, prisma_path, write_file, internal_deps=internal_deps_map, is_docker=True, features=resource_features)
|
|
409
410
|
TSConfig.backend(resource_path, prisma_path, write_file, internal_deps=internal_deps_map, is_docker=False, features=resource_features)
|
|
410
411
|
|
package/package.json
CHANGED
package/templates/Tiltfile.hbs
CHANGED
|
@@ -229,7 +229,12 @@ for app_service in _app_resources_list:
|
|
|
229
229
|
Watchers.setup_package_json(_app_resources_list, should_enable)
|
|
230
230
|
|
|
231
231
|
# Apply focus mode filter
|
|
232
|
-
# Build known Tilt resource names
|
|
232
|
+
# Build known Tilt resource names (and a stack-name -> resource-name index) from
|
|
233
|
+
# discovered services to filter focus list. Focus targets are stack names (e.g.
|
|
234
|
+
# "app", "billing") from spec.master, which do NOT always match the resource
|
|
235
|
+
# name prefix (stack "app" maps to resources "dashboard-api"/"dashboard-app",
|
|
236
|
+
# not "app-*") - so stack membership must be resolved explicitly rather than
|
|
237
|
+
# assumed via string prefix.
|
|
233
238
|
_KNOWN_TILT_RESOURCES = set()
|
|
234
239
|
_KNOWN_TILT_RESOURCES.add('service-discovery-daemon')
|
|
235
240
|
_KNOWN_TILT_RESOURCES.add('init-networks')
|
|
@@ -241,8 +246,10 @@ _KNOWN_TILT_RESOURCES.add('infisical-redis')
|
|
|
241
246
|
_KNOWN_TILT_RESOURCES.add('traefik')
|
|
242
247
|
_KNOWN_TILT_RESOURCES.add('verdaccio')
|
|
243
248
|
_KNOWN_TILT_RESOURCES.add('golden-layers-build')
|
|
249
|
+
_STACK_TO_RESOURCE_NAMES = {}
|
|
244
250
|
for _KNOWN_SVC in _app_resources_list:
|
|
245
251
|
_KNOWN_SVC_NAME = _KNOWN_SVC.get('name', '')
|
|
252
|
+
_KNOWN_SVC_STACK = _KNOWN_SVC.get('stack', '')
|
|
246
253
|
if _KNOWN_SVC_NAME:
|
|
247
254
|
for _KNOWN_RES in _KNOWN_SVC.get('resources', []):
|
|
248
255
|
_KNOWN_RES_NAME = _KNOWN_RES.get('name', '')
|
|
@@ -250,11 +257,19 @@ for _KNOWN_SVC in _app_resources_list:
|
|
|
250
257
|
_KNOWN_TILT_RESOURCES.add(_KNOWN_RES_NAME)
|
|
251
258
|
_KNOWN_TILT_RESOURCES.add(_KNOWN_RES_NAME + '-run-only')
|
|
252
259
|
_KNOWN_TILT_RESOURCES.add(_KNOWN_RES_NAME + '-config-gen')
|
|
260
|
+
if _KNOWN_SVC_STACK:
|
|
261
|
+
_STACK_TO_RESOURCE_NAMES.setdefault(_KNOWN_SVC_STACK, [])
|
|
262
|
+
_STACK_TO_RESOURCE_NAMES[_KNOWN_SVC_STACK].append(_KNOWN_RES_NAME)
|
|
253
263
|
if FOCUS_MODE and FOCUS_ENABLED_RESOURCES:
|
|
254
264
|
_FILTERED_RESOURCES = []
|
|
255
265
|
for _R in FOCUS_ENABLED_RESOURCES:
|
|
256
266
|
if _R in _KNOWN_TILT_RESOURCES:
|
|
257
267
|
_FILTERED_RESOURCES.append(_R)
|
|
268
|
+
elif _R in _STACK_TO_RESOURCE_NAMES:
|
|
269
|
+
for _STACK_RES_NAME in _STACK_TO_RESOURCE_NAMES[_R]:
|
|
270
|
+
_FILTERED_RESOURCES.append(_STACK_RES_NAME)
|
|
271
|
+
_FILTERED_RESOURCES.append(_STACK_RES_NAME + '-run-only')
|
|
272
|
+
_FILTERED_RESOURCES.append(_STACK_RES_NAME + '-config-gen')
|
|
258
273
|
else:
|
|
259
274
|
_MATCHED = [kr for kr in _KNOWN_TILT_RESOURCES if kr != 'service-discovery-daemon' and kr.startswith(_R + '-')]
|
|
260
275
|
_FILTERED_RESOURCES.extend(_MATCHED)
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
# Core infrastructure services - minimal footprint for rapid development
|
|
41
41
|
|
|
42
42
|
PRE_ALPHA_RESOURCES = {
|
|
43
|
-
{{#each
|
|
43
|
+
{{#each phases.pre_alpha.enabledStacks}}
|
|
44
44
|
"{{this}}": True, # {{lookup ../serviceDescriptions this}}
|
|
45
45
|
{{/each}}
|
|
46
46
|
}
|
|
@@ -51,7 +51,7 @@ PRE_ALPHA_RESOURCES = {
|
|
|
51
51
|
# Essential business services for alpha launch.
|
|
52
52
|
|
|
53
53
|
ALPHA_RESOURCES = {
|
|
54
|
-
{{#each
|
|
54
|
+
{{#each phases.alpha.enabledStacks}}
|
|
55
55
|
"{{this}}": False, # {{lookup ../serviceDescriptions this}}
|
|
56
56
|
{{/each}}
|
|
57
57
|
}
|
|
@@ -62,7 +62,7 @@ ALPHA_RESOURCES = {
|
|
|
62
62
|
# Additional services for beta release.
|
|
63
63
|
|
|
64
64
|
BETA_RESOURCES = {
|
|
65
|
-
{{#each
|
|
65
|
+
{{#each phases.beta.enabledStacks}}
|
|
66
66
|
"{{this}}": False, # {{lookup ../serviceDescriptions this}}
|
|
67
67
|
{{/each}}
|
|
68
68
|
}
|
|
@@ -74,7 +74,7 @@ BETA_RESOURCES = {
|
|
|
74
74
|
# To enable, remove from this list and add to appropriate stack above.
|
|
75
75
|
|
|
76
76
|
OUT_OF_SCOPE_RESOURCES = [
|
|
77
|
-
{{#each
|
|
77
|
+
{{#each phases.out_of_scope.enabledStacks}}
|
|
78
78
|
"{{this}}", # {{lookup ../serviceDescriptions this}}
|
|
79
79
|
{{/each}}
|
|
80
80
|
]
|
|
@@ -152,6 +152,13 @@ PROJECT = struct(
|
|
|
152
152
|
NAME = "{{project.name}}",
|
|
153
153
|
VERSION = "{{project.version}}",
|
|
154
154
|
|
|
155
|
+
PHASES = struct(
|
|
156
|
+
PRE_ALPHA = FOCUS_PRE_ALPHA,
|
|
157
|
+
ALPHA = FOCUS_ALPHA,
|
|
158
|
+
BETA = FOCUS_BETA,
|
|
159
|
+
),
|
|
160
|
+
|
|
161
|
+
# Backward compatibility for older extension code that reads PROJECT.STACKS.
|
|
155
162
|
STACKS = struct(
|
|
156
163
|
PRE_ALPHA = FOCUS_PRE_ALPHA,
|
|
157
164
|
ALPHA = FOCUS_ALPHA,
|