@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.
Files changed (70) hide show
  1. package/discovery/discovery_orchestrator.star +4 -4
  2. package/discovery/manifest/loading.star +9 -5
  3. package/discovery/manifest/normalize.star +3 -3
  4. package/discovery/manifest/validation.star +1 -1
  5. package/discovery/validation.star +1 -1
  6. package/dist/commands/doctor.d.ts.map +1 -1
  7. package/dist/commands/doctor.js +120 -6
  8. package/dist/commands/doctor.js.map +1 -1
  9. package/dist/commands/help.js +1 -1
  10. package/dist/commands/help.js.map +1 -1
  11. package/dist/commands/project.d.ts.map +1 -1
  12. package/dist/commands/project.js +27 -23
  13. package/dist/commands/project.js.map +1 -1
  14. package/dist/commands/resource.js +1 -1
  15. package/dist/commands/resource.js.map +1 -1
  16. package/dist/commands/up.d.ts.map +1 -1
  17. package/dist/commands/up.js +2 -48
  18. package/dist/commands/up.js.map +1 -1
  19. package/dist/generator/template-engine.d.ts +1 -1
  20. package/dist/generator/template-engine.d.ts.map +1 -1
  21. package/dist/generator/template-engine.js +96 -44
  22. package/dist/generator/template-engine.js.map +1 -1
  23. package/dist/index.d.ts +1 -1
  24. package/dist/types/index.d.ts +20 -7
  25. package/dist/types/index.d.ts.map +1 -1
  26. package/dist/types/index.js.map +1 -1
  27. package/dist/utils/constants.d.ts +1 -0
  28. package/dist/utils/constants.d.ts.map +1 -1
  29. package/dist/utils/constants.js +11 -0
  30. package/dist/utils/constants.js.map +1 -1
  31. package/dist/utils/resource-features.d.ts +1 -1
  32. package/dist/utils/resource-features.js +1 -1
  33. package/dist/utils/service-urls.d.ts +30 -0
  34. package/dist/utils/service-urls.d.ts.map +1 -0
  35. package/dist/utils/service-urls.js +93 -0
  36. package/dist/utils/service-urls.js.map +1 -0
  37. package/dist/utils/stack-features.d.ts +4 -4
  38. package/dist/utils/stack-features.d.ts.map +1 -1
  39. package/dist/utils/stack-features.js +1 -1
  40. package/dist/utils/stack-features.js.map +1 -1
  41. package/engine/REFACTORING_MANIFEST_SYSTEM.md +1 -1
  42. package/engine/lifecycle/orchestrator.star +4 -3
  43. package/engine/schemas/service-schema.json +5 -5
  44. package/engine/topologies/platform/docker/compose/compose.star +44 -24
  45. package/engine/topologies/platform/docker/constants.star +4 -0
  46. package/engine/topologies/platform/docker/generators/golden_docker_generator_v2.star +1 -0
  47. package/engine/topologies/platform/docker/layers/l4_runtime_layers.star +10 -6
  48. package/engine/topologies/platform/docker/networking/api_path_constants.star +30 -0
  49. package/engine/topologies/platform/docker/networking/traefik.star +2 -2
  50. package/engine/topologies/platform/net/AGENTS.md +64 -0
  51. package/engine/topologies/platform/security/AGENTS.md +49 -0
  52. package/engine/topologies/platform/state/AGENTS.md +64 -0
  53. package/engine/topologies/tilt/config/profiles.star +16 -2
  54. package/engine/topologies/tilt/generators/typescript/frontend_tsconfig.star +21 -9
  55. package/engine/topologies/tilt/generators/vite/backend.star +1 -1
  56. package/engine/topologies/tilt/generators/vite/frontend.star +2 -1
  57. package/engine/topologies/tilt/generators/vite/helpers.star +1 -1
  58. package/engine/topologies/tilt/manifest/constants.star +1 -1
  59. package/engine/topologies/tilt/manifest/mapper.star +2 -2
  60. package/engine/topologies/tilt/manifest/parser.star +2 -2
  61. package/engine/topologies/tilt/manifest/schema.star +2 -2
  62. package/engine/topologies/tilt/manifest/tests/test_loader_parser.star +3 -3
  63. package/engine/topologies/tilt/manifest/tests/test_validator.star +2 -2
  64. package/engine/topologies/tilt/manifest/validator.star +7 -7
  65. package/engine/topologies/tilt/resources/orchestrator/generators/env.star +3 -2
  66. package/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +3 -2
  67. package/package.json +1 -1
  68. package/templates/Tiltfile.hbs +16 -1
  69. package/templates/spec.master.hbs +11 -4
  70. 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 (in resource aliases).
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
- # When tsconfig is in .autogenerated/ folder, paths are relative to parent
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
- "@/*": ["../src/*"],
48
+ "@/*": [src_prefix + "src/*"],
44
49
  "@/autogenerated/*": ["./.autogenerated/*"]
45
50
  }
46
- include_paths = ["../src/**/*"]
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
- "types": ["node"],
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
- "../__tests__/**/*",
90
- "../**/*.test.ts",
91
- "../**/tests/**/*",
92
- "../**/*.steps.ts",
93
- "../**/*.spec.ts"
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('features', [])
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.get('basePath', '/' + stack + 's')
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('features', []) and os.environ.get('TDK_LICENSE_KEY', '') != ''
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 = [
@@ -155,7 +155,7 @@ MANIFEST_DEFAULTS = {
155
155
  'healthCheckPath': HEALTH_CHECK_PATH,
156
156
  'internalPort': BASE_PORT_FRONTEND,
157
157
  'replicas': 1,
158
- 'features': [],
158
+ 'featuresEnabled': [],
159
159
  'envVars': {},
160
160
  'syncs': None,
161
161
  'dependsOn': [],
@@ -31,7 +31,7 @@ FIELD_MAPPINGS = {
31
31
  'replicas': ['replicas', 'instances', 'count', 'spec.replicas', 'metadata.replicas'],
32
32
 
33
33
  # Feature flags
34
- 'features': ['features', 'capabilities', 'spec.features', 'enabledFeatures', 'app.features'],
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
- 'features': internal_manifest.get('features', []),
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('features', [])
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
- 'features': {
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': 'features', 'contains': 'prisma'},
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
- 'features': ['nats'],
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
- 'features': ['prisma'], # Override
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['features'], "Should overlay features")
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
- 'features': ['prisma'],
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
- 'features': ['nats', 'prisma'],
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 'features' in manifest:
319
+ if 'featuresEnabled' in manifest:
320
320
  stats['fields_checked'] += 1
321
- features = manifest['features']
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': 'features', 'count': len(features), 'max': VALIDATION_THRESHOLDS['max_features']},
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('features', [])
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', 'features': features},
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
- # Get basePath from manifest or default to /{stack}
137
- base_path = manifest.get('basePath', '/' + stack)
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('features', [])
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tdk-landscape/tdk-cli-core",
3
- "version": "1.3.32",
3
+ "version": "1.3.36",
4
4
  "description": "TDK CLI - Tilt Development Kit command line interface",
5
5
  "keywords": [
6
6
  "tdk",
@@ -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 from discovered services to filter focus list
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 stacks.pre_alpha.services}}
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 stacks.alpha.services}}
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 stacks.beta.services}}
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 stacks.out_of_scope.services}}
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,