Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(next): make astro:env stable #11679

Merged
merged 27 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f108a14
chore: add todos
florian-lefebvre Aug 12, 2024
31a3b3a
feat: work on types and codegen
florian-lefebvre Aug 12, 2024
da6b613
feat: work on todos
florian-lefebvre Aug 12, 2024
18978c7
feat: update adapters
florian-lefebvre Aug 12, 2024
d835645
chore: update tests
florian-lefebvre Aug 12, 2024
5bee7ff
fix: do not use fs mock
florian-lefebvre Aug 12, 2024
d878774
feat: work on jsdoc
florian-lefebvre Aug 12, 2024
b3bc57b
fix: feature validation test
florian-lefebvre Aug 13, 2024
2ed705c
chore: changeset
florian-lefebvre Aug 13, 2024
9d6dd21
chore: remove setup chunk
florian-lefebvre Aug 13, 2024
0962b38
feat: do not use TLA
florian-lefebvre Aug 13, 2024
ff30bfb
Merge branch 'next' into feat/unflag-astro-env
florian-lefebvre Aug 13, 2024
74be1bd
fix: only create env reference if needed
florian-lefebvre Aug 13, 2024
9727e9f
Merge branch 'feat/unflag-astro-env' of https://github.com/withastro/…
florian-lefebvre Aug 13, 2024
23ea790
Merge remote-tracking branch 'origin/next' into feat/unflag-astro-env
florian-lefebvre Aug 14, 2024
a497e44
feat: misc
florian-lefebvre Aug 14, 2024
24e9150
feat: bump peer deps
florian-lefebvre Aug 14, 2024
e181f3f
feat: address reviews
florian-lefebvre Aug 15, 2024
5c97a92
feat: update changeset
florian-lefebvre Aug 15, 2024
acce9b8
Merge branch 'next' into feat/unflag-astro-env
florian-lefebvre Aug 16, 2024
7940a64
Merge branch 'next' into feat/unflag-astro-env
florian-lefebvre Aug 19, 2024
03abff1
feat: address reviews
florian-lefebvre Aug 20, 2024
5bde388
feat: update errors
florian-lefebvre Aug 20, 2024
8e87103
Merge branch 'next' into feat/unflag-astro-env
florian-lefebvre Aug 20, 2024
f7a156d
fix: fixture
florian-lefebvre Aug 20, 2024
24c5720
Sarah edit of changeset
sarah11918 Aug 20, 2024
fbb460e
tiny changeset edit
sarah11918 Aug 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .changeset/eighty-boxes-applaud.md
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
'astro': major
---

Makes `astro:env` stable

To upgrade, update your Astro config:

```diff
import { defineConfig, envField } from 'astro/config'

export default defineConfig({
- experimental: {
env: {
schema: {
FOO: envField.string({ /* ... */ })
}
}
- }
})
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved
```
6 changes: 6 additions & 0 deletions .changeset/selfish-impalas-grin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@astrojs/vercel': major
'@astrojs/node': major
---

Adds stable support for `astro:env`
1 change: 1 addition & 0 deletions packages/astro/client.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// <reference types="vite/types/import-meta.d.ts" />
/// <reference path="./types/content.d.ts" />
/// <reference path="./types/actions.d.ts" />
/// <reference path="./types/env.d.ts" />

// eslint-disable-next-line @typescript-eslint/no-namespace
declare namespace App {
Expand Down
212 changes: 70 additions & 142 deletions packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1755,6 +1755,76 @@ export interface AstroUserConfig {
*/
legacy?: object;

/**
* @docs
* @name env
* @type {object}
* @default `{}`
* @version 5.0.0
* @description
*
* Holds `astro:env` options.
*/
env?: {
/**
* @docs
* @name env.schema
* @type {EnvSchema}
* @default `{}`
* @version 5.0.0
* @description
*
* An object that uses `envField` to define the data type (`string`, `number`, or `boolean`) and properties of your environment variables: `context` (client or server), `access` (public or secret), a `default` value to use, and whether or not this environment variable is `optional` (defaults to `false`).
* ```js
* // astro.config.mjs
* import { defineConfig, envField } from "astro/config"
*
* export default defineConfig({
* experimental: {
* env: {
* schema: {
* API_URL: envField.string({ context: "client", access: "public", optional: true }),
* PORT: envField.number({ context: "server", access: "public", default: 4321 }),
* API_SECRET: envField.string({ context: "server", access: "secret" }),
* }
* }
* }
* })
* ```
*/
schema?: EnvSchema;

/**
* @docs
* @name env.validateSecrets
* @type {boolean}
* @default `false`
* @version 5.0.0
* @description
*
* Whether or not to validate secrets on the server when starting the dev server or running a build.
*
* By default, only public variables are validated on the server when starting the dev server or a build, and private variables are validated at runtime only. If enabled, private variables will also be checked on start. This is useful in some continuous integration (CI) pipelines to make sure all your secrets are correctly set before deploying.
*
* ```js
* // astro.config.mjs
* import { defineConfig, envField } from "astro/config"
*
* export default defineConfig({
* experimental: {
* env: {
* schema: {
* // ...
* },
* validateSecrets: true
* }
* }
* })
* ```
*/
validateSecrets?: boolean;
};

/**
* @docs
* @kind heading
Expand Down Expand Up @@ -1977,148 +2047,6 @@ export interface AstroUserConfig {
*/
globalRoutePriority?: boolean;

/**
* @docs
* @name experimental.env
* @type {object}
* @default `undefined`
* @version 4.10.0
* @description
*
* Enables experimental `astro:env` features.
*
* The `astro:env` API lets you configure a type-safe schema for your environment variables, and indicate whether they should be available on the server or the client. Import and use your defined variables from the appropriate `/client` or `/server` module:
*
* ```astro
* ---
* import { API_URL } from "astro:env/client"
* import { API_SECRET_TOKEN } from "astro:env/server"
*
* const data = await fetch(`${API_URL}/users`, {
* method: "GET",
* headers: {
* "Content-Type": "application/json",
* "Authorization": `Bearer ${API_SECRET_TOKEN}`
* },
* })
* ---
*
* <script>
* import { API_URL } from "astro:env/client"
*
* fetch(`${API_URL}/ping`)
* </script>
* ```
*
* To define the data type and properties of your environment variables, declare a schema in your Astro config in `experimental.env.schema`. The `envField` helper allows you define your variable as a string, number, or boolean and pass properties in an object:
*
* ```js
* // astro.config.mjs
* import { defineConfig, envField } from "astro/config"
*
* export default defineConfig({
* experimental: {
* env: {
* schema: {
* API_URL: envField.string({ context: "client", access: "public", optional: true }),
* PORT: envField.number({ context: "server", access: "public", default: 4321 }),
* API_SECRET: envField.string({ context: "server", access: "secret" }),
* }
* }
* }
* })
* ```
*
* There are currently four data types supported: strings, numbers, booleans and enums.
*
* There are three kinds of environment variables, determined by the combination of `context` (client or server) and `access` (secret or public) settings defined in your [`env.schema`](#experimentalenvschema):
*
* - **Public client variables**: These variables end up in both your final client and server bundles, and can be accessed from both client and server through the `astro:env/client` module:
*
* ```js
* import { API_URL } from "astro:env/client"
* ```
*
* - **Public server variables**: These variables end up in your final server bundle and can be accessed on the server through the `astro:env/server` module:
*
* ```js
* import { PORT } from "astro:env/server"
* ```
*
* - **Secret server variables**: These variables are not part of your final bundle and can be accessed on the server through the `astro:env/server` module. The `getSecret()` helper function can be used to retrieve secrets not specified in the schema. Its implementation is provided by your adapter and defaults to `process.env`:
*
* ```js
* import { API_SECRET, getSecret } from "astro:env/server"
*
* const SECRET_NOT_IN_SCHEMA = getSecret("SECRET_NOT_IN_SCHEMA") // string | undefined
* ```
*
* **Note:** Secret client variables are not supported because there is no safe way to send this data to the client. Therefore, it is not possible to configure both `context: "client"` and `access: "secret"` in your schema.
*
* For a complete overview, and to give feedback on this experimental API, see the [Astro Env RFC](https://github.com/withastro/roadmap/blob/feat/astro-env-rfc/proposals/0046-astro-env.md).
*/
env?: {
/**
* @docs
* @name experimental.env.schema
* @kind h4
* @type {EnvSchema}
* @default `undefined`
* @version 4.10.0
* @description
*
* An object that uses `envField` to define the data type (`string`, `number`, or `boolean`) and properties of your environment variables: `context` (client or server), `access` (public or secret), a `default` value to use, and whether or not this environment variable is `optional` (defaults to `false`).
* ```js
* // astro.config.mjs
* import { defineConfig, envField } from "astro/config"
*
* export default defineConfig({
* experimental: {
* env: {
* schema: {
* API_URL: envField.string({ context: "client", access: "public", optional: true }),
* PORT: envField.number({ context: "server", access: "public", default: 4321 }),
* API_SECRET: envField.string({ context: "server", access: "secret" }),
* }
* }
* }
* })
* ```
*/
schema?: EnvSchema;

/**
* @docs
* @name experimental.env.validateSecrets
* @kind h4
* @type {boolean}
* @default `false`
* @version 4.11.6
* @description
*
* Whether or not to validate secrets on the server when starting the dev server or running a build.
*
* By default, only public variables are validated on the server when starting the dev server or a build, and private variables are validated at runtime only. If enabled, private variables will also be checked on start. This is useful in some continuous integration (CI) pipelines to make sure all your secrets are correctly set before deploying.
*
* ```js
* // astro.config.mjs
* import { defineConfig, envField } from "astro/config"
*
* export default defineConfig({
* experimental: {
* env: {
* schema: {
* // ...
* },
* validateSecrets: true
* }
* }
* })
* ```
*/
validateSecrets?: boolean;
};

/**
* @docs
* @name experimental.serverIslands
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/container/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ function createManifest(
i18n: manifest?.i18n,
checkOrigin: false,
middleware: manifest?.middleware ?? middleware ?? defaultMiddleware,
experimentalEnvGetSecretEnabled: false,
envGetSecretEnabled: false,
};
}

Expand Down
3 changes: 1 addition & 2 deletions packages/astro/src/core/app/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ export type SSRManifest = {
i18n: SSRManifestI18n | undefined;
middleware: MiddlewareHandler;
checkOrigin: boolean;
// TODO: remove experimental prefix
experimentalEnvGetSecretEnabled: boolean;
envGetSecretEnabled: boolean;
};

export type SSRManifestI18n = {
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/base-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export abstract class Pipeline {
}
// In SSR, getSecret should fail by default. Setting it here will run before the
// adapter override.
if (callSetGetEnv && manifest.experimentalEnvGetSecretEnabled) {
if (callSetGetEnv && manifest.envGetSecretEnabled) {
setGetEnv(() => {
throw new AstroError(AstroErrorData.EnvUnsupportedGetSecret);
}, true);
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/build/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,6 @@ function createBuildManifest(
buildFormat: settings.config.build.format,
middleware,
checkOrigin: settings.config.security?.checkOrigin ?? false,
experimentalEnvGetSecretEnabled: false,
envGetSecretEnabled: false,
};
}
5 changes: 0 additions & 5 deletions packages/astro/src/core/build/plugins/plugin-chunks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ export function vitePluginChunks(): VitePlugin {
if (id.includes('astro/dist/runtime')) {
return 'astro';
}
// Place `astro/env/setup` import in its own chunk to prevent Rollup's TLA bug
// https://github.com/rollup/rollup/issues/4708
if (id.includes('astro/dist/env/setup')) {
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved
return 'astro/env-setup';
}
},
});
},
Expand Down
3 changes: 1 addition & 2 deletions packages/astro/src/core/build/plugins/plugin-manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,7 @@ function buildManifest(
buildFormat: settings.config.build.format,
checkOrigin: settings.config.security?.checkOrigin ?? false,
serverIslandNameMap: Array.from(settings.serverIslandNameMap),
experimentalEnvGetSecretEnabled:
settings.config.experimental.env !== undefined &&
envGetSecretEnabled:
(settings.adapter?.supportedAstroFeatures.envGetSecret ?? 'unsupported') !== 'unsupported',
};
}
25 changes: 12 additions & 13 deletions packages/astro/src/core/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,17 @@ export const ASTRO_CONFIG_DEFAULTS = {
legacy: {},
redirects: {},
security: {},
env: {
schema: {},
validateSecrets: false,
},
experimental: {
actions: false,
directRenderScript: false,
contentCollectionCache: false,
clientPrerender: false,
globalRoutePriority: false,
serverIslands: false,
env: {
validateSecrets: false,
},
},
} satisfies AstroUserConfig & { server: { open: boolean } };

Expand Down Expand Up @@ -505,6 +506,14 @@ export const AstroConfigSchema = z.object({
})
.optional()
.default(ASTRO_CONFIG_DEFAULTS.security),
env: z
.object({
schema: EnvSchema.optional().default(ASTRO_CONFIG_DEFAULTS.env.schema),
validateSecrets: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.env.validateSecrets),
})
.strict()
.optional()
.default(ASTRO_CONFIG_DEFAULTS.env),
experimental: z
.object({
actions: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.actions),
Expand All @@ -524,16 +533,6 @@ export const AstroConfigSchema = z.object({
.boolean()
.optional()
.default(ASTRO_CONFIG_DEFAULTS.experimental.globalRoutePriority),
env: z
.object({
schema: EnvSchema.optional(),
validateSecrets: z
.boolean()
.optional()
.default(ASTRO_CONFIG_DEFAULTS.experimental.env.validateSecrets),
})
.strict()
.optional(),
serverIslands: z
.boolean()
.optional()
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/create-vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export async function createVite(
// the build to run very slow as the filewatcher is triggered often.
mode !== 'build' && vitePluginAstroServer({ settings, logger, fs }),
envVitePlugin({ settings }),
astroEnv({ settings, mode, fs, sync }),
astroEnv({ settings, mode, sync }),
markdownVitePlugin({ settings, logger }),
htmlVitePlugin(),
mdxVitePlugin(),
Expand Down
8 changes: 3 additions & 5 deletions packages/astro/src/core/sync/setup-env-ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,10 @@ export async function setUpEnvTs({
filename: ACTIONS_TYPES_FILE,
meetsCondition: () => fs.existsSync(new URL(ACTIONS_TYPES_FILE, settings.dotAstroDir)),
},
];
if (settings.config.experimental.env) {
injectedTypes.push({
{
filename: ENV_TYPES_FILE,
});
}
},
];

if (fs.existsSync(envTsPath)) {
const initialEnvContents = await fs.promises.readFile(envTsPath, 'utf-8');
Expand Down
Loading
Loading