@teamscala/service-boot 0.23.546 → 0.23.548
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/package.json +312 -312
- package/src/inject-declared-env.ts +32 -0
- package/src/load-service-install-row.ts +5 -3
- package/src/mount-orpc-router.test.ts +2 -2
- package/src/mount-orpc-router.ts +1 -1
- package/src/orpc-contract-rows.json +369 -0
- package/src/register-api-routes.ts +89 -83
- package/src/select-service-api-routes.ts +82 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ServiceInstallConfig } from "./load-service-install-row";
|
|
7
|
+
|
|
8
|
+
export type EnvSource = Record<string, string | undefined>;
|
|
9
|
+
|
|
10
|
+
export interface DeclaredEnvResult {
|
|
11
|
+
config: ServiceInstallConfig;
|
|
12
|
+
injected: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function injectDeclaredEnv(
|
|
16
|
+
config: ServiceInstallConfig,
|
|
17
|
+
source: EnvSource = process.env,
|
|
18
|
+
): DeclaredEnvResult {
|
|
19
|
+
const declared: unknown = (config as Record<string, unknown>).env_vars;
|
|
20
|
+
const injected: string[] = [];
|
|
21
|
+
if (!Array.isArray(declared)) return { config, injected };
|
|
22
|
+
for (const entry of declared) {
|
|
23
|
+
const name = (entry as { name?: unknown } | null)?.name;
|
|
24
|
+
if (typeof name !== "string" || name.length === 0) continue;
|
|
25
|
+
const value = source[name];
|
|
26
|
+
if (typeof value === "string" && value.length > 0) {
|
|
27
|
+
(config as Record<string, unknown>)[name] = value;
|
|
28
|
+
injected.push(name);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return { config, injected };
|
|
32
|
+
}
|
|
@@ -15,15 +15,16 @@ import {
|
|
|
15
15
|
ServiceInstallValidationError,
|
|
16
16
|
} from "@teamscala/registry-schemas/registry-schemas/service-install";
|
|
17
17
|
import * as v from "valibot";
|
|
18
|
+
import { injectDeclaredEnv } from "./inject-declared-env";
|
|
18
19
|
|
|
19
20
|
const BOOT_ROW_KEYS = [
|
|
20
21
|
"access",
|
|
21
|
-
"api_routes",
|
|
22
22
|
"app_port",
|
|
23
23
|
"auth",
|
|
24
24
|
"block_packages",
|
|
25
25
|
"boot_hooks",
|
|
26
26
|
"brand_org",
|
|
27
|
+
"env_vars",
|
|
27
28
|
"home_path",
|
|
28
29
|
"kind",
|
|
29
30
|
"orpc_router",
|
|
@@ -73,7 +74,8 @@ export async function loadServiceInstallRow(
|
|
|
73
74
|
) as Record<string, unknown>;
|
|
74
75
|
enforceExplicitRenderMode(serviceSlug, rawConfig);
|
|
75
76
|
const config = v.parse(ServiceInstallBootSchema, rawConfig);
|
|
76
|
-
|
|
77
|
+
const declared = injectDeclaredEnv(config);
|
|
78
|
+
return { success: true, config: declared.config };
|
|
77
79
|
} catch (err) {
|
|
78
80
|
if (err instanceof v.ValiError) {
|
|
79
81
|
const issues = err.issues
|
|
@@ -90,7 +92,7 @@ export async function loadServiceInstallRow(
|
|
|
90
92
|
};
|
|
91
93
|
}
|
|
92
94
|
if (err instanceof RegistryMissingError) {
|
|
93
|
-
const sql = `INSERT INTO registry_entries (type, slug, config, is_active) VALUES ('service_install', '${serviceSlug}', '{"kind":"ui","render_mode":"public","port":null,"page_routes":[],"providers":[],"
|
|
95
|
+
const sql = `INSERT INTO registry_entries (type, slug, config, is_active) VALUES ('service_install', '${serviceSlug}', '{"kind":"ui","render_mode":"public","port":null,"page_routes":[],"providers":[],"block_packages":[],"teamgbg_packages":[],"env_vars":[]}'::jsonb, true);`;
|
|
94
96
|
return {
|
|
95
97
|
success: false,
|
|
96
98
|
error: "row_not_found",
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// overwritten on the next run. The rationale each assertion carries moved
|
|
8
8
|
// with it into the band.
|
|
9
9
|
import * as __scalaReal_teamscala_event_log_record_event from "@teamscala/event-log/record-event";
|
|
10
|
-
import * as __scalaReal_teamscala_tool_executor_configure from "@teamscala/tool-executor/configure";
|
|
10
|
+
import * as __scalaReal_teamscala_tool_executor_configure from "@teamscala/tool-executor-substrate/configure";
|
|
11
11
|
import * as __scalaReal_teamscala_orpc_configure from "@teamscala/orpc/configure";
|
|
12
12
|
import * as __scalaReal_teamscala_orpc_app_router from "@teamscala/orpc/app-router";
|
|
13
13
|
|
|
@@ -85,7 +85,7 @@ describe("mountOrpcRouter generated-artifact seam", () => {
|
|
|
85
85
|
...__scalaReal_teamscala_orpc_configure,
|
|
86
86
|
getPrisma: () => ({}),
|
|
87
87
|
}));
|
|
88
|
-
mock.module("@teamscala/tool-executor/configure", () => ({
|
|
88
|
+
mock.module("@teamscala/tool-executor-substrate/configure", () => ({
|
|
89
89
|
...__scalaReal_teamscala_tool_executor_configure,
|
|
90
90
|
configure: (opts: Record<string, unknown>) => {
|
|
91
91
|
seenKeys = Object.keys(opts);
|
package/src/mount-orpc-router.ts
CHANGED
|
@@ -97,7 +97,7 @@ export async function mountOrpcRouter(
|
|
|
97
97
|
);
|
|
98
98
|
|
|
99
99
|
const { configure: configureToolExecutor } = await import(
|
|
100
|
-
"@teamscala/tool-executor/configure"
|
|
100
|
+
"@teamscala/tool-executor-substrate/configure"
|
|
101
101
|
);
|
|
102
102
|
const [{ getCallerContext }, { decryptSecretConfig }] =
|
|
103
103
|
await Promise.all([
|
|
@@ -314,6 +314,329 @@
|
|
|
314
314
|
"suite_type": "function_call",
|
|
315
315
|
"slug": "service-boot:absent-manifest-verdict-reserves-never-ran"
|
|
316
316
|
},
|
|
317
|
+
{
|
|
318
|
+
"args": [
|
|
319
|
+
{
|
|
320
|
+
"kind": "backend",
|
|
321
|
+
"env_vars": [
|
|
322
|
+
{
|
|
323
|
+
"name": "ABSENT_VAR",
|
|
324
|
+
"required": true
|
|
325
|
+
}
|
|
326
|
+
]
|
|
327
|
+
},
|
|
328
|
+
{}
|
|
329
|
+
],
|
|
330
|
+
"note": "The deployed configureEnv contract says absence fails the JOB at use (required() throws, the hook answers 503), never the boot. Injection mirrors that: a declared name missing from the environment is skipped, leaving the consumer guard as the failure surface.",
|
|
331
|
+
"label": "a declared env var absent from the environment is not injected and boot is not fatal",
|
|
332
|
+
"expect": {
|
|
333
|
+
"config": {
|
|
334
|
+
"kind": "backend",
|
|
335
|
+
"env_vars": [
|
|
336
|
+
{
|
|
337
|
+
"name": "ABSENT_VAR",
|
|
338
|
+
"required": true
|
|
339
|
+
}
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
"injected": []
|
|
343
|
+
},
|
|
344
|
+
"export": "injectDeclaredEnv",
|
|
345
|
+
"module": "src/inject-declared-env.ts",
|
|
346
|
+
"package": "@teamscala/service-boot",
|
|
347
|
+
"suite_type": "function_call",
|
|
348
|
+
"slug": "service-boot:an-absent-declared-var-is-left-to-the-consumer-guard"
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
"args": [
|
|
352
|
+
{
|
|
353
|
+
"kind": "backend",
|
|
354
|
+
"env_vars": [
|
|
355
|
+
{
|
|
356
|
+
"name": "EMPTY_VAR",
|
|
357
|
+
"required": true
|
|
358
|
+
}
|
|
359
|
+
]
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"EMPTY_VAR": ""
|
|
363
|
+
}
|
|
364
|
+
],
|
|
365
|
+
"note": "The deployed raw() reader treats an empty string as absent. Injecting one would mask the consumer guard with a value that behaves as missing.",
|
|
366
|
+
"label": "an empty-string environment value is not injected",
|
|
367
|
+
"expect": {
|
|
368
|
+
"config": {
|
|
369
|
+
"kind": "backend",
|
|
370
|
+
"env_vars": [
|
|
371
|
+
{
|
|
372
|
+
"name": "EMPTY_VAR",
|
|
373
|
+
"required": true
|
|
374
|
+
}
|
|
375
|
+
]
|
|
376
|
+
},
|
|
377
|
+
"injected": []
|
|
378
|
+
},
|
|
379
|
+
"export": "injectDeclaredEnv",
|
|
380
|
+
"module": "src/inject-declared-env.ts",
|
|
381
|
+
"package": "@teamscala/service-boot",
|
|
382
|
+
"suite_type": "function_call",
|
|
383
|
+
"slug": "service-boot:an-empty-env-value-is-not-injected"
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
"args": [
|
|
387
|
+
{
|
|
388
|
+
"kind": "backend",
|
|
389
|
+
"env_vars": [
|
|
390
|
+
{
|
|
391
|
+
"required": true
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
"name": ""
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
"name": "GOOD_VAR"
|
|
398
|
+
}
|
|
399
|
+
]
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"GOOD_VAR": "ok-value"
|
|
403
|
+
}
|
|
404
|
+
],
|
|
405
|
+
"note": "The schema types env_vars items as v.unknown(), so the boot stage must not trust item shape: an entry carrying no name and an entry carrying an empty name are skipped and boot never throws, while the next well-formed declaration still lands on the config.",
|
|
406
|
+
"label": "env_vars entries without a usable name are skipped while the named one still lands",
|
|
407
|
+
"expect": {
|
|
408
|
+
"config": {
|
|
409
|
+
"kind": "backend",
|
|
410
|
+
"GOOD_VAR": "ok-value",
|
|
411
|
+
"env_vars": [
|
|
412
|
+
{
|
|
413
|
+
"required": true
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
"name": ""
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
"name": "GOOD_VAR"
|
|
420
|
+
}
|
|
421
|
+
]
|
|
422
|
+
},
|
|
423
|
+
"injected": [
|
|
424
|
+
"GOOD_VAR"
|
|
425
|
+
]
|
|
426
|
+
},
|
|
427
|
+
"export": "injectDeclaredEnv",
|
|
428
|
+
"module": "src/inject-declared-env.ts",
|
|
429
|
+
"package": "@teamscala/service-boot",
|
|
430
|
+
"suite_type": "function_call",
|
|
431
|
+
"slug": "service-boot:an-env-declaration-without-a-usable-name-is-skipped"
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
"args": [
|
|
435
|
+
[
|
|
436
|
+
{
|
|
437
|
+
"slug": "npm-registry-hook",
|
|
438
|
+
"config": {
|
|
439
|
+
"path": "/webhooks/npm/registry",
|
|
440
|
+
"method": "POST",
|
|
441
|
+
"handler": "npm-registry-hook",
|
|
442
|
+
"service": "scala-sync-worker",
|
|
443
|
+
"auth_required": false
|
|
444
|
+
}
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
"slug": "email.send",
|
|
448
|
+
"config": {
|
|
449
|
+
"path": "/api/rpc/email/send",
|
|
450
|
+
"method": "POST",
|
|
451
|
+
"service": "scala-email-sender",
|
|
452
|
+
"handler_slug": "email.send",
|
|
453
|
+
"auth_required": true
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
],
|
|
457
|
+
"scala-sync-worker",
|
|
458
|
+
[
|
|
459
|
+
"npm-registry-hook"
|
|
460
|
+
]
|
|
461
|
+
],
|
|
462
|
+
"note": "Bug 01a15334 (Joe's Developer, delivery 01a15336): the shape of the row that was declared and never served - config.handler (not handler_slug) on POST /webhooks/npm/registry for scala-sync-worker.",
|
|
463
|
+
"label": "a row naming its mount handler in config.handler is selected for its own service and maps onto the handler registry",
|
|
464
|
+
"expect": [
|
|
465
|
+
{
|
|
466
|
+
"slug": "npm-registry-hook",
|
|
467
|
+
"mount": {
|
|
468
|
+
"path": "/webhooks/npm/registry",
|
|
469
|
+
"method": "post",
|
|
470
|
+
"handlerSlug": "npm-registry-hook"
|
|
471
|
+
},
|
|
472
|
+
"service": "scala-sync-worker",
|
|
473
|
+
"notMounted": null
|
|
474
|
+
}
|
|
475
|
+
],
|
|
476
|
+
"export": "selectServiceApiRoutes",
|
|
477
|
+
"module": "src/select-service-api-routes.ts",
|
|
478
|
+
"package": "@teamscala/service-boot",
|
|
479
|
+
"suite_type": "function_call",
|
|
480
|
+
"slug": "service-boot:api-route-config-handler-maps-onto-the-mount-registry"
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
"args": [
|
|
484
|
+
[
|
|
485
|
+
{
|
|
486
|
+
"slug": "email.send",
|
|
487
|
+
"config": {
|
|
488
|
+
"path": "/api/rpc/email/send",
|
|
489
|
+
"method": "POST",
|
|
490
|
+
"service": "scala-email-sender",
|
|
491
|
+
"handler_slug": "email.send",
|
|
492
|
+
"auth_required": true
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
],
|
|
496
|
+
"scala-email-sender",
|
|
497
|
+
[
|
|
498
|
+
"npm-registry-hook"
|
|
499
|
+
]
|
|
500
|
+
],
|
|
501
|
+
"note": "api_route/email.send names handler_slug email.send, but no server_package in the workspace registers it and service_install/scala-email-sender declares no server_packages. Boot reports it by name on every start instead of claiming the route is served.",
|
|
502
|
+
"label": "a row naming a handler no mounted package registered is named as unserved instead of silently 404ing or bricking the service",
|
|
503
|
+
"expect": [
|
|
504
|
+
{
|
|
505
|
+
"slug": "email.send",
|
|
506
|
+
"mount": null,
|
|
507
|
+
"service": "scala-email-sender",
|
|
508
|
+
"notMounted": "handler-not-mounted"
|
|
509
|
+
}
|
|
510
|
+
],
|
|
511
|
+
"export": "selectServiceApiRoutes",
|
|
512
|
+
"module": "src/select-service-api-routes.ts",
|
|
513
|
+
"package": "@teamscala/service-boot",
|
|
514
|
+
"suite_type": "function_call",
|
|
515
|
+
"slug": "service-boot:api-route-row-naming-an-unmounted-handler-is-reported-unserved"
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
"args": [
|
|
519
|
+
[
|
|
520
|
+
{
|
|
521
|
+
"slug": "npm-registry-hook",
|
|
522
|
+
"config": {
|
|
523
|
+
"path": "/webhooks/npm/registry",
|
|
524
|
+
"method": "POST",
|
|
525
|
+
"handler": "npm-registry-hook",
|
|
526
|
+
"service": "scala-sync-worker",
|
|
527
|
+
"auth_required": false
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
],
|
|
531
|
+
"scala-sync-worker-ts-dev",
|
|
532
|
+
[
|
|
533
|
+
"npm-registry-hook"
|
|
534
|
+
]
|
|
535
|
+
],
|
|
536
|
+
"note": "Raw string equality on the deployable name matched at most one lane and failed silently (capability-slug.ts incident): the row names the capability, the lane arrives as <capability>-<lang>-<tier>.",
|
|
537
|
+
"label": "a dev-lane service is served the rows its capability declares, the join select-service-routes.ts already makes for page_route",
|
|
538
|
+
"expect": [
|
|
539
|
+
{
|
|
540
|
+
"slug": "npm-registry-hook",
|
|
541
|
+
"mount": {
|
|
542
|
+
"path": "/webhooks/npm/registry",
|
|
543
|
+
"method": "post",
|
|
544
|
+
"handlerSlug": "npm-registry-hook"
|
|
545
|
+
},
|
|
546
|
+
"service": "scala-sync-worker",
|
|
547
|
+
"notMounted": null
|
|
548
|
+
}
|
|
549
|
+
],
|
|
550
|
+
"export": "selectServiceApiRoutes",
|
|
551
|
+
"module": "src/select-service-api-routes.ts",
|
|
552
|
+
"package": "@teamscala/service-boot",
|
|
553
|
+
"suite_type": "function_call",
|
|
554
|
+
"slug": "service-boot:api-route-row-reaches-the-dev-lane-through-the-capability-slug"
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
"args": [
|
|
558
|
+
[
|
|
559
|
+
{
|
|
560
|
+
"slug": "fn-chat-complete",
|
|
561
|
+
"config": {
|
|
562
|
+
"path": "/api/rpc/fn/chat/complete",
|
|
563
|
+
"method": "POST",
|
|
564
|
+
"service": "scala-ai",
|
|
565
|
+
"handler_type": "orpc_fn",
|
|
566
|
+
"auth_required": true
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
],
|
|
570
|
+
"scala-ai",
|
|
571
|
+
[
|
|
572
|
+
"chat-stream"
|
|
573
|
+
]
|
|
574
|
+
],
|
|
575
|
+
"note": "handler_type orpc_fn rows are served by the generated ORPC router (orpc-bundle.pkl), not by a mount handler; boot must not claim them or fail on them.",
|
|
576
|
+
"label": "a row that names no mount handler is reported as declared, never mounted onto the mount registry",
|
|
577
|
+
"expect": [
|
|
578
|
+
{
|
|
579
|
+
"slug": "fn-chat-complete",
|
|
580
|
+
"mount": null,
|
|
581
|
+
"service": "scala-ai",
|
|
582
|
+
"notMounted": "declares-no-mount-handler"
|
|
583
|
+
}
|
|
584
|
+
],
|
|
585
|
+
"export": "selectServiceApiRoutes",
|
|
586
|
+
"module": "src/select-service-api-routes.ts",
|
|
587
|
+
"package": "@teamscala/service-boot",
|
|
588
|
+
"suite_type": "function_call",
|
|
589
|
+
"slug": "service-boot:api-route-row-without-a-mount-handler-is-declared-not-mounted"
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
"args": [
|
|
593
|
+
[
|
|
594
|
+
{
|
|
595
|
+
"slug": "npm-registry-hook",
|
|
596
|
+
"config": {
|
|
597
|
+
"path": "/webhooks/npm/registry",
|
|
598
|
+
"method": "POST",
|
|
599
|
+
"handler": "npm-registry-hook",
|
|
600
|
+
"service": "scala-sync-worker",
|
|
601
|
+
"auth_required": false
|
|
602
|
+
}
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
"slug": "scala-forms-get--api-places-autocomplete",
|
|
606
|
+
"config": {
|
|
607
|
+
"path": "/api/places/autocomplete",
|
|
608
|
+
"method": "GET",
|
|
609
|
+
"service": "scala-forms",
|
|
610
|
+
"handler_slug": "geocode-autocomplete",
|
|
611
|
+
"auth_required": false
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
],
|
|
615
|
+
"scala-forms",
|
|
616
|
+
[
|
|
617
|
+
"geocode-autocomplete"
|
|
618
|
+
]
|
|
619
|
+
],
|
|
620
|
+
"note": "A row belonging to a different service must not leak into this service's route table or its boot log.",
|
|
621
|
+
"label": "another service's row is neither mounted nor reported - selection is by this service's capability alone",
|
|
622
|
+
"expect": [
|
|
623
|
+
{
|
|
624
|
+
"slug": "scala-forms-get--api-places-autocomplete",
|
|
625
|
+
"mount": {
|
|
626
|
+
"path": "/api/places/autocomplete",
|
|
627
|
+
"method": "get",
|
|
628
|
+
"handlerSlug": "geocode-autocomplete"
|
|
629
|
+
},
|
|
630
|
+
"service": "scala-forms",
|
|
631
|
+
"notMounted": null
|
|
632
|
+
}
|
|
633
|
+
],
|
|
634
|
+
"export": "selectServiceApiRoutes",
|
|
635
|
+
"module": "src/select-service-api-routes.ts",
|
|
636
|
+
"package": "@teamscala/service-boot",
|
|
637
|
+
"suite_type": "function_call",
|
|
638
|
+
"slug": "service-boot:api-route-rows-of-another-service-are-not-selected"
|
|
639
|
+
},
|
|
317
640
|
{
|
|
318
641
|
"args": [
|
|
319
642
|
"@teamscala/cli-session"
|
|
@@ -1396,6 +1719,52 @@
|
|
|
1396
1719
|
"suite_type": "function_call",
|
|
1397
1720
|
"slug": "service-boot:decide-content-page-floor-resource-type-route-is-null"
|
|
1398
1721
|
},
|
|
1722
|
+
{
|
|
1723
|
+
"args": [
|
|
1724
|
+
{
|
|
1725
|
+
"kind": "backend",
|
|
1726
|
+
"env_vars": [
|
|
1727
|
+
{
|
|
1728
|
+
"name": "NPM_HOOK_SECRET",
|
|
1729
|
+
"required": true
|
|
1730
|
+
},
|
|
1731
|
+
{
|
|
1732
|
+
"name": "ABSENT_VAR",
|
|
1733
|
+
"required": false
|
|
1734
|
+
}
|
|
1735
|
+
]
|
|
1736
|
+
},
|
|
1737
|
+
{
|
|
1738
|
+
"NPM_HOOK_SECRET": "s3cret-value"
|
|
1739
|
+
}
|
|
1740
|
+
],
|
|
1741
|
+
"note": "Bug 01a15334 / subtask 01a153d0-f3b7. The deployed npm-registry-hook handler reads env.NPM_HOOK_SECRET through configureEnv(ctx.config), which stores the whole mount config and indexes it by bare top-level key (integration-sync-runtime/src/env.ts, read from the running scala-sync-worker container). The loader must therefore carry each declared name as a top-level string on the config it returns.",
|
|
1742
|
+
"label": "a declared env var present in the process environment lands on the boot config under its own name",
|
|
1743
|
+
"expect": {
|
|
1744
|
+
"config": {
|
|
1745
|
+
"kind": "backend",
|
|
1746
|
+
"env_vars": [
|
|
1747
|
+
{
|
|
1748
|
+
"name": "NPM_HOOK_SECRET",
|
|
1749
|
+
"required": true
|
|
1750
|
+
},
|
|
1751
|
+
{
|
|
1752
|
+
"name": "ABSENT_VAR",
|
|
1753
|
+
"required": false
|
|
1754
|
+
}
|
|
1755
|
+
],
|
|
1756
|
+
"NPM_HOOK_SECRET": "s3cret-value"
|
|
1757
|
+
},
|
|
1758
|
+
"injected": [
|
|
1759
|
+
"NPM_HOOK_SECRET"
|
|
1760
|
+
]
|
|
1761
|
+
},
|
|
1762
|
+
"export": "injectDeclaredEnv",
|
|
1763
|
+
"module": "src/inject-declared-env.ts",
|
|
1764
|
+
"package": "@teamscala/service-boot",
|
|
1765
|
+
"suite_type": "function_call",
|
|
1766
|
+
"slug": "service-boot:declared-env-vars-carry-their-process-values-into-the-mount-config"
|
|
1767
|
+
},
|
|
1399
1768
|
{
|
|
1400
1769
|
"args": [
|
|
1401
1770
|
{
|