@platformatic/foundation 3.63.0-alpha.3 → 3.63.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
@@ -85,6 +85,7 @@ export type ConfigurationOptions<T = {}> = Partial<{
85
85
  replaceEnv: boolean
86
86
  replaceEnvIgnore: string[]
87
87
  onMissingEnv: (key: string) => string | undefined
88
+ strictEnv: boolean | 'warn'
88
89
  fixPaths: boolean
89
90
  logger: Logger
90
91
  root: string
@@ -181,6 +182,7 @@ export declare const SourceMissingError: FastifyError
181
182
  export declare const RootMissingError: FastifyError
182
183
  export declare const SchemaMustBeDefinedError: FastifyError
183
184
  export declare const ConfigurationDoesNotValidateAgainstSchemaError: FastifyError
185
+ export declare const MissingEnvVariablesError: FastifyError
184
186
 
185
187
  // Execution types
186
188
  export declare function executeWithTimeout<T> (promise: Promise<T>, timeout: number, timeoutValue?: any): Promise<T>
@@ -12,6 +12,7 @@ import {
12
12
  CannotParseConfigFileError,
13
13
  ConfigurationDoesNotValidateAgainstSchemaError,
14
14
  InvalidConfigFileExtensionError,
15
+ MissingEnvVariablesError,
15
16
  RootMissingError,
16
17
  SourceMissingError
17
18
  } from './errors.js'
@@ -382,10 +383,13 @@ export async function loadEnv (root, ignoreProcessEnv = false, additionalEnv = {
382
383
  const baseEnv = ignoreProcessEnv ? {} : process.env
383
384
  const envFromFile = envFile ? parseEnv(await readFile(envFile, 'utf-8')) : {}
384
385
 
386
+ // The env file provides fallback defaults: variables already set in the real
387
+ // environment (and explicit programmatic values) take precedence over it,
388
+ // matching the dotenv/docker-compose/Vite convention.
385
389
  return {
390
+ ...envFromFile,
386
391
  ...baseEnv,
387
- ...additionalEnv,
388
- ...envFromFile
392
+ ...additionalEnv
389
393
  }
390
394
  }
391
395
 
@@ -442,6 +446,16 @@ export function replaceEnv (config, env, onMissingEnv, ignore) {
442
446
  return config
443
447
  }
444
448
 
449
+ function normalizeStrictEnv (value) {
450
+ if (value === 'warn') {
451
+ return 'warn'
452
+ } else if (value === 'false' || value === '') {
453
+ return false
454
+ }
455
+
456
+ return Boolean(value)
457
+ }
458
+
445
459
  export async function loadConfiguration (source, schema, options = {}) {
446
460
  const {
447
461
  validate: shouldValidate,
@@ -453,6 +467,7 @@ export async function loadConfiguration (source, schema, options = {}) {
453
467
  replaceEnv: shouldReplaceEnv,
454
468
  replaceEnvIgnore,
455
469
  onMissingEnv,
470
+ strictEnv: strictEnvOption,
456
471
  fixPaths,
457
472
  logger,
458
473
  skipMetadata,
@@ -487,7 +502,42 @@ export async function loadConfiguration (source, schema, options = {}) {
487
502
  env.PLT_ROOT = root
488
503
 
489
504
  if (shouldReplaceEnv) {
490
- config = replaceEnv(config, env, onMissingEnv, replaceEnvIgnore)
505
+ const missingEnv = new Set()
506
+
507
+ config = replaceEnv(
508
+ config,
509
+ env,
510
+ key => {
511
+ const value = onMissingEnv?.(key)
512
+
513
+ if (typeof value === 'undefined' || value === null) {
514
+ missingEnv.add(key)
515
+ }
516
+
517
+ return value
518
+ },
519
+ replaceEnvIgnore
520
+ )
521
+
522
+ // strictEnv can be set programmatically or in the configuration file itself, either at the top level
523
+ // (runtime configurations) or in the runtime property (capabilities configurations).
524
+ const strictEnv = normalizeStrictEnv(strictEnvOption ?? config.strictEnv ?? config.runtime?.strictEnv)
525
+
526
+ if (strictEnv && missingEnv.size > 0) {
527
+ const keys = Array.from(missingEnv).sort().join(', ')
528
+
529
+ 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
+ }
537
+ } else {
538
+ throw new MissingEnvVariablesError(keys)
539
+ }
540
+ }
491
541
  }
492
542
 
493
543
  const moduleInfo = extractModuleFromSchemaUrl(config)
package/lib/errors.js CHANGED
@@ -56,3 +56,7 @@ export const ConfigurationDoesNotValidateAgainstSchemaError = createError(
56
56
  `${ERROR_PREFIX}_CONFIGURATION_DOES_NOT_VALIDATE_AGAINST_SCHEMA`,
57
57
  'The configuration does not validate against the configuration schema'
58
58
  )
59
+ export const MissingEnvVariablesError = createError(
60
+ `${ERROR_PREFIX}_MISSING_ENV_VARIABLES`,
61
+ 'The configuration references the following environment variables which are not set: %s'
62
+ )
package/lib/module.js CHANGED
@@ -17,6 +17,11 @@ export const applicationTypes = [
17
17
  { name: '@platformatic/next', label: 'Next.js', dependencies: ['next'] },
18
18
  { name: '@platformatic/remix', label: 'Remix', dependencies: ['@remix-run/dev'] },
19
19
  { name: '@platformatic/astro', label: 'Astro', dependencies: ['astro'] },
20
+ { name: '@platformatic/react-router', label: 'React Router', dependencies: ['@react-router/dev'] },
21
+ { name: '@platformatic/nuxt', label: 'Nuxt', dependencies: ['nuxt'] },
22
+ { name: '@platformatic/tanstack', label: 'TanStack Start', dependencies: ['@tanstack/react-start'] },
23
+ // Nitro applications often use Vite, so Nitro must be checked first.
24
+ { name: '@platformatic/nitro', label: 'Nitro', dependencies: ['nitro', 'nitropack'] },
20
25
  // Since Vite is often used with other frameworks, we must check for Vite last amongst frontend frameworks
21
26
  { name: '@platformatic/vite', label: 'Vite', dependencies: ['vite'] },
22
27
  {
package/lib/schema.js CHANGED
@@ -396,7 +396,8 @@ export const server = {
396
396
  portAssignment: {
397
397
  type: 'string',
398
398
  enum: ['shared', 'perWorkerIncrement'],
399
- description: 'Configures how entrypoint server worker ports are assigned. When set to shared, all workers listen on the same port. When set to perWorkerIncrement, each worker will use its own port, starting from port (worker 0).'
399
+ description:
400
+ 'Configures how entrypoint server worker ports are assigned. When set to shared, all workers listen on the same port. When set to perWorkerIncrement, each worker will use its own port, starting from port (worker 0).'
400
401
  },
401
402
  backlog: {
402
403
  type: 'integer',
@@ -791,7 +792,8 @@ export const telemetry = {
791
792
  type: 'string'
792
793
  }
793
794
  ],
794
- description: 'Enable the OpenTelemetry diagnostic logger. Diagnostic messages are forwarded to the Platformatic global logger using the current logger level.'
795
+ description:
796
+ 'Enable the OpenTelemetry diagnostic logger. Diagnostic messages are forwarded to the Platformatic global logger using the current logger level.'
795
797
  }
796
798
  },
797
799
  required: ['applicationName'],
@@ -1125,7 +1127,7 @@ export const runtimeProperties = {
1125
1127
  },
1126
1128
  { type: 'string' }
1127
1129
  ],
1128
- default: 10000
1130
+ default: 30000
1129
1131
  },
1130
1132
  application: {
1131
1133
  anyOf: [
@@ -1533,6 +1535,11 @@ export const runtimeProperties = {
1533
1535
  envfile: {
1534
1536
  type: 'string'
1535
1537
  },
1538
+ strictEnv: {
1539
+ anyOf: [{ type: 'boolean' }, { type: 'string' }],
1540
+ description:
1541
+ 'When set to true, the configuration loading fails if a {PLT_*} placeholder references an environment variable which is not set. When set to "warn", a warning listing the missing variables is logged but the placeholders are still replaced with an empty string. Defaults to false.'
1542
+ },
1536
1543
  sourceMaps: {
1537
1544
  type: 'boolean',
1538
1545
  default: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/foundation",
3
- "version": "3.63.0-alpha.3",
3
+ "version": "3.63.0",
4
4
  "description": "Platformatic Foundation",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -37,7 +37,7 @@
37
37
  "c8": "^11.0.0",
38
38
  "cleaner-spec-reporter": "^0.5.0",
39
39
  "eslint": "9",
40
- "fastify": "^5.7.0",
40
+ "fastify": "^5.0.0",
41
41
  "neostandard": "^0.12.0",
42
42
  "pino": "^9.9.0",
43
43
  "pino-test": "^1.0.1",