@platformatic/foundation 3.64.0 → 3.66.0

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/index.d.ts CHANGED
@@ -6,6 +6,7 @@ import { LevelWithSilentOrString, Logger } from 'pino'
6
6
 
7
7
  // Symbols
8
8
  export declare const kCanceled: unique symbol
9
+ export declare const kEnvFileFallbackKeys: unique symbol
9
10
  export declare const kFailedImport: unique symbol
10
11
  export declare const kHandledError: unique symbol
11
12
  export declare const kMetadata: unique symbol
@@ -18,7 +18,7 @@ import {
18
18
  } from './errors.js'
19
19
  import { isFileAccessible } from './file-system.js'
20
20
  import { loadModule, splitModuleFromVersion } from './module.js'
21
- import { kMetadata } from './symbols.js'
21
+ import { kEnvFileFallbackKeys, kMetadata } from './symbols.js'
22
22
 
23
23
  const { parse: parseJSON5, stringify: rawStringifyJSON5 } = JSON5
24
24
  const { parse: parseTOML, stringify: stringifyTOML } = toml
@@ -386,11 +386,21 @@ export async function loadEnv (root, ignoreProcessEnv = false, additionalEnv = {
386
386
  // The env file provides fallback defaults: variables already set in the real
387
387
  // environment (and explicit programmatic values) take precedence over it,
388
388
  // matching the dotenv/docker-compose/Vite convention.
389
- return {
389
+ const env = {
390
390
  ...envFromFile,
391
391
  ...baseEnv,
392
392
  ...additionalEnv
393
393
  }
394
+
395
+ // Keys whose only source is the env file are not real environment variables, they are defaults:
396
+ // a more specific env file, like the one of a single application inside a runtime, must still be
397
+ // able to override them. The list is attached non enumerably, so spreading, Object.keys,
398
+ // JSON.stringify and structuredClone of the returned environment are all unchanged.
399
+ const fallbackKeys = Object.keys(envFromFile).filter(key => !(key in baseEnv) && !(key in additionalEnv))
400
+
401
+ Object.defineProperty(env, kEnvFileFallbackKeys, { value: fallbackKeys, enumerable: false })
402
+
403
+ return env
394
404
  }
395
405
 
396
406
  export function replaceEnv (config, env, onMissingEnv, ignore) {
@@ -503,6 +513,7 @@ export async function loadConfiguration (source, schema, options = {}) {
503
513
 
504
514
  if (shouldReplaceEnv) {
505
515
  const missingEnv = new Set()
516
+ const fallbackEnv = new Set()
506
517
 
507
518
  config = replaceEnv(
508
519
  config,
@@ -512,6 +523,11 @@ export async function loadConfiguration (source, schema, options = {}) {
512
523
 
513
524
  if (typeof value === 'undefined' || value === null) {
514
525
  missingEnv.add(key)
526
+ } else {
527
+ // The variable is not set: it only has a value because onMissingEnv provided a fallback.
528
+ // Track it separately so that strictEnv can still report it, as a fallback can silently
529
+ // mask a misconfiguration.
530
+ fallbackEnv.add(key)
515
531
  }
516
532
 
517
533
  return value
@@ -523,17 +539,31 @@ export async function loadConfiguration (source, schema, options = {}) {
523
539
  // (runtime configurations) or in the runtime property (capabilities configurations).
524
540
  const strictEnv = normalizeStrictEnv(strictEnvOption ?? config.strictEnv ?? config.runtime?.strictEnv)
525
541
 
542
+ function warn (message) {
543
+ if (logger) {
544
+ logger.warn(message)
545
+ } else {
546
+ process.emitWarning(message)
547
+ }
548
+ }
549
+
550
+ // Variables resolved by a fallback are always reported as a warning, never as an error: they did
551
+ // resolve to a value, so failing on them would change which configurations are able to boot.
552
+ // This is emitted before handling the missing ones so that a throw does not swallow it.
553
+ if (strictEnv && fallbackEnv.size > 0) {
554
+ const keys = Array.from(fallbackEnv).sort().join(', ')
555
+
556
+ warn(
557
+ 'The configuration references the following environment variables which are not set ' +
558
+ `and have been replaced by a fallback value: ${keys}`
559
+ )
560
+ }
561
+
526
562
  if (strictEnv && missingEnv.size > 0) {
527
563
  const keys = Array.from(missingEnv).sort().join(', ')
528
564
 
529
565
  if (strictEnv === 'warn') {
530
- const message = `The configuration references the following environment variables which are not set: ${keys}`
531
-
532
- if (logger) {
533
- logger.warn(message)
534
- } else {
535
- process.emitWarning(message)
536
- }
566
+ warn(`The configuration references the following environment variables which are not set: ${keys}`)
537
567
  } else {
538
568
  throw new MissingEnvVariablesError(keys)
539
569
  }
package/lib/symbols.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export const kCanceled = Symbol('plt.foundation.canceled')
2
+ export const kEnvFileFallbackKeys = Symbol('plt.foundation.envFileFallbackKeys')
2
3
  export const kFailedImport = Symbol('plt.foundation.failedImport')
3
4
  export const kHandledError = Symbol('plt.foundation.handledError')
4
5
  export const kMetadata = Symbol('plt.foundation.metadata')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/foundation",
3
- "version": "3.64.0",
3
+ "version": "3.66.0",
4
4
  "description": "Platformatic Foundation",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -50,6 +50,7 @@
50
50
  "scripts": {
51
51
  "test": "npm run test:types && node --test --test-reporter=cleaner-spec-reporter --test-concurrency=1 --test-timeout=2000000 test/*.test.js test/**/*.test.js",
52
52
  "test:types": "tstyche",
53
- "lint": "eslint"
53
+ "lint": "eslint",
54
+ "lint:fix": "eslint --fix"
54
55
  }
55
56
  }