withastro / astro

The web framework for content-driven websites. ⭐️ Star to support our work!
https://astro.build
Other
45.98k stars 2.43k forks source link

Improved astro:env errors #11381

Closed xino1010 closed 2 months ago

xino1010 commented 3 months ago

Astro Info

- astro: 4.11.3
- node: 18.18.2

If this issue only occurs in one browser, which browser is a problem?

No response

Describe the Bug

import { defineConfig, envField } from "astro/config";

import node from "@astrojs/node";

// https://astro.build/config
export default defineConfig({
  experimental: {
    env: {
      schema: {
        ...,
        DB_PASS: envField.string({
          context: "server",
          access: "secret",
        }),
        ...,
      },
    },
  },
  output: "server",
  adapter: node({
    mode: "standalone",
  }),
});

Use the env var, for example,src/data-source.ts.

import { DB_HOST, DB_NAME, DB_PASS, DB_PORT, DB_USER } from "astro:env/server";
import { DataSource } from "typeorm";
import { Todo } from "./entities/todo";

const dataSource: DataSource = new DataSource({
  type: "mysql",
  host: DB_HOST,
  port: DB_PORT,
  username: DB_USER,
  password: DB_PASS,
  database: DB_NAME,
  entities: [Todo],
  synchronize: true,
  logging: false,
});

export const getDataSource = async (): Promise<DataSource> => {
  if (!dataSource.isInitialized) {
    try {
      await dataSource.initialize();
    } catch (e) {
      console.error("Failed to initialize data source", e);
      process.exit(1);
    }
  }
  return dataSource;
};
npm run build
npm run preview
22:14:07 [ERROR] EnvInvalidVariable: The following environment variable does not match the data type and/or properties defined in `experimental.env.schema`: DB_NAME is not of type string
    at createInvalidVariableError (file:///Users/dani/git/astro-dummy/dist/server/chunks/astro/env-setup_K_VhW_hQ.mjs:134:10)
    at _internalGetSecret (file:///Users/dani/git/astro-dummy/dist/server/chunks/data-source_DM7eOVU6.mjs:66:8)
    at file:///Users/dani/git/astro-dummy/dist/server/chunks/data-source_DM7eOVU6.mjs:78:1
    at ModuleJob.run (node:internal/modules/esm/module_job:194:25)

Defining the var with access public, there is not error:

import { defineConfig, envField } from "astro/config";

import node from "@astrojs/node";

// https://astro.build/config
export default defineConfig({
  experimental: {
    env: {
      schema: {
        ...,
        DB_PASS: envField.string({
          context: "server",
          access: "public",
        }),
        ...,
      },
    },
  },
  output: "server",
  adapter: node({
    mode: "standalone",
  }),
});

What's the expected result?

Launch the application without any error.

Link to Minimal Reproducible Example

https://github.com/xino1010/astro-env-example

Participation

florian-lefebvre commented 3 months ago

The reproduction does not show this issue, please update it

github-actions[bot] commented 3 months ago

Hello @xino1010. Please provide a minimal reproduction using a GitHub repository or StackBlitz. Issues marked with needs repro will be closed if they have no activity within 3 days.

xino1010 commented 3 months ago

@florian-lefebvre here you'll find an example to reproduce the bug.

florian-lefebvre commented 3 months ago

I think this is because at https://github.com/withastro/astro/blob/main/packages/integrations/node/src/server.ts#L11 (and same for vercel and netlify), process.env is not loaded with .env. Maybe we should call loadEnv? @ematipico

ematipico commented 3 months ago

I think this is because at main/packages/integrations/node/src/server.ts#L11 (and same for vercel and netlify), process.env is not loaded with .env. Maybe we should call loadEnv? @ematipico

Should we? astro preview is meant to run a production-like server, and I doubt users will use .env to load their secrets in production. Those secrets should injected via process.env. In this particular case, the secret should be passed like this

CHAT_GPT_SECRET=123456 astro preview
xino1010 commented 3 months ago

I think this is because at main/packages/integrations/node/src/server.ts#L11 (and same for vercel and netlify), process.env is not loaded with .env. Maybe we should call loadEnv? @ematipico

Should we? astro preview is meant to run a production-like server, and I doubt users will use .env to load their secrets in production. Those secrets should injected via process.env. In this particular case, the secret should be passed like this

CHAT_GPT_SECRET=123456 astro preview

Maybe we're talking about two different things:

import node from "@astrojs/node";

// https://astro.build/config export default defineConfig({ output: "server", adapter: node({ mode: "standalone", }), experimental: { env: { schema: { CHAT_GPT_KEY: envField.string({ context: "server", access: "secret", }), }, }, }, });


```typescript
---
import { CHAT_GPT_KEY } from "astro:env/server";
console.log(CHAT_GPT_KEY);
---

so the issue here is, in preview and build mode, the secret var is not accessible.

11:18:15 [ERROR] EnvInvalidVariable: The following environment variable does not match the data type and/or properties defined in `experimental.env.schema`: CHAT_GPT_KEY is not of type string
florian-lefebvre commented 3 months ago

Yeah I agree errors need improvements, regarding what validation rule is failing exactly (eg. startsWith)