-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New Integration: Server-Only Modules (#67)
* implementation * add test * update lockfile * add changeset * add docs * fail on ts, mts, cts, tsx, js, mjs, cjs, jsx * switch emoji
- Loading branch information
Showing
12 changed files
with
209 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"astro-server-only-modules": major | ||
--- | ||
|
||
Initial release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# astro-server-only-modules 🔐 | ||
|
||
This **[Astro integration][astro-integration]** allows you to make sure you never leak security-sensitive code to the browser. | ||
|
||
- <strong>[Why astro-server-only-modules?](#why-astro-server-only-modules)</strong> | ||
- <strong>[Installation](#installation)</strong> | ||
- <strong>[Usage](#usage)</strong> | ||
- <strong>[Troubleshooting](#troubleshooting)</strong> | ||
- <strong>[Contributing](#contributing)</strong> | ||
- <strong>[Changelog](#changelog)</strong> | ||
|
||
## Why astro-server-only-modules? | ||
|
||
In a large codebase, it can be difficult to keep track of how code is being shared and where. This becomes a security risk when you have critical information that should only be available to the server. There are parts of your infrastructure that the browser (and therefore, a malicious user) does not need to be privy to. | ||
|
||
This integration allows you to delineate the context of your code to only include it in the server app. If one of the modules ending with `.server.ts` extension accidentally gets imported by client-side, directly or indirectly, the build will fail. | ||
|
||
## Installation | ||
|
||
### Manual Install | ||
|
||
First, install the `astro-server-only-modules` package using your package manager. If you're using npm or aren't sure, run this in the terminal: | ||
|
||
```sh | ||
npm install astro-server-only-modules | ||
``` | ||
|
||
Then, apply this integration to your `astro.config.*` file using the `integrations` property: | ||
|
||
```diff lang="js" "serverOnlyModules()" | ||
// astro.config.mjs | ||
import { defineConfig } from 'astro/config'; | ||
+ import serverOnlyModules from 'astro-server-only-modules'; | ||
|
||
export default defineConfig({ | ||
// ... | ||
+ integrations: [serverOnlyModules()], | ||
// ^^^^^^^^^^^^^^^^^ | ||
}); | ||
``` | ||
|
||
## Usage | ||
|
||
Once the integration is installed and added to the configuration file, rename modules that should only be used within the server to end with `.server.ts`. If one of these modules accidentally gets imported by client-side, directly or indirectly, the build will fail. | ||
|
||
## Troubleshooting | ||
|
||
For help, check out the `Discussions` tab on the [GitHub repo](https://github.com/lilnasy/gratelets/discussions). | ||
|
||
## Contributing | ||
|
||
This package is maintained by [lilnasy](https://github.com/lilnasy) independently from Astro. The integration code is located at [packages/server-only-modules/integration.ts](https://github.com/lilnasy/gratelets/blob/main/packages/server-only-modules/integration.ts). You're welcome to contribute by submitting an issue or opening a PR! | ||
|
||
## Changelog | ||
|
||
See [CHANGELOG.md](https://github.com/lilnasy/gratelets/blob/main/packages/server-only-modules/CHANGELOG.md) for a history of changes to this integration. | ||
|
||
[astro-integration]: https://docs.astro.build/en/guides/integrations-guide/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import type { AstroIntegration } from "astro" | ||
|
||
interface Options {} | ||
|
||
/** | ||
* Prevents modules with the extension `.server.ts` from being imported into client-side code. | ||
*/ | ||
export default function (_?: Options): AstroIntegration { | ||
let buildingFor: "server" | "client" | undefined = undefined | ||
return { | ||
name: "server-only-modules", | ||
hooks: { | ||
"astro:config:setup" ({ updateConfig }) { | ||
updateConfig({ vite: { plugins: [{ | ||
name: "server-only-modules/vite", | ||
load(specifier) { | ||
if (buildingFor === "client") { | ||
if ( | ||
specifier.endsWith(".server.ts") || | ||
specifier.endsWith(".server.mts") || | ||
specifier.endsWith(".server.cts") || | ||
specifier.endsWith(".server.tsx") || | ||
specifier.endsWith(".server.js") || | ||
specifier.endsWith(".server.mjs") || | ||
specifier.endsWith(".server.cjs") || | ||
specifier.endsWith(".server.jsx") | ||
) { | ||
throw new ServerOnlyModule | ||
} | ||
} | ||
}, | ||
}] } }) | ||
}, | ||
"astro:build:setup" ({ target }) { | ||
buildingFor = target | ||
} | ||
} | ||
} | ||
} | ||
|
||
class ServerOnlyModule extends Error { | ||
name = "ServerOnlyModule" | ||
constructor() { | ||
super(`Cannot import a server-only module in the client build.`) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"name": "astro-server-only-modules", | ||
"version": "0.0.0", | ||
"description": "Make sure you never leak security-sensitive code to the browser.", | ||
"author": "Arsh", | ||
"license": "Public Domain", | ||
"keywords": [ | ||
"withastro", | ||
"astro-component" | ||
], | ||
"homepage": "https://github.com/lilnasy/gratelets/tree/main/packages/server-only-modules", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/lilnasy/gratelets", | ||
"directory": "packages/server-only-modules" | ||
}, | ||
"files": [ | ||
"integration.ts" | ||
], | ||
"exports": { | ||
".": "./integration.ts" | ||
}, | ||
"scripts": { | ||
"test": "pnpm -w test server-only-modules.test.ts" | ||
}, | ||
"type": "module", | ||
"devDependencies": { | ||
"@types/node": "20", | ||
"astro": "4" | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { defineConfig } from "astro/config" | ||
import serverOnlyModules from "astro-server-only-modules" | ||
|
||
// https://astro.build/config | ||
export default defineConfig({ | ||
integrations: process.env.INCLUDE === "true" ? [serverOnlyModules()] : [], | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"name": "@test/server-only-modules", | ||
"private": true, | ||
"dependencies": { | ||
"astro": "4", | ||
"astro-server-only-modules": "workspace:*" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> | ||
<meta name="viewport" content="width=device-width" /> | ||
<meta name="generator" content={Astro.generator} /> | ||
<title>Astro</title> | ||
<script> | ||
import { X } from "../x.server" | ||
console.log(X) | ||
</script> | ||
</head> | ||
<body> | ||
<h1>Astro</h1> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const X = "X" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { describe, expect, test } from "vitest" | ||
import { build } from "./utils.ts" | ||
|
||
describe("astro-server-only-modules", () => { | ||
test("Build succeeds without the integration.", async () => { | ||
process.env.INCLUDE = "false" | ||
await build("./fixtures/server-only-modules") | ||
}) | ||
test("Build fails with the integration.", async () => { | ||
process.env.INCLUDE = "true" | ||
try { | ||
await build("./fixtures/server-only-modules") | ||
expect.unreachable() | ||
} catch {} | ||
}) | ||
}) |