mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
Require that ASTRO_STUDIO_REMOTE_DB_URL is defined at runtime (#10533)
* Require that ASTRO_STUDIO_REMOTE_DB_URL is defined at runtime * Add changeset * Fix build
This commit is contained in:
parent
8306ce1ff7
commit
6576f5d458
12 changed files with 160 additions and 4 deletions
5
.changeset/curly-donkeys-sleep.md
Normal file
5
.changeset/curly-donkeys-sleep.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@astrojs/db": patch
|
||||
---
|
||||
|
||||
Ensure ASTRO_STUDIO_APP_TOKEN is found at runtime
|
|
@ -44,6 +44,7 @@ export async function cmd({
|
|||
virtualModContents = getStudioVirtualModContents({
|
||||
tables: dbConfig.tables ?? {},
|
||||
appToken: appToken.token,
|
||||
isBuild: false,
|
||||
});
|
||||
} else {
|
||||
virtualModContents = getLocalVirtualModContents({
|
||||
|
|
|
@ -37,9 +37,13 @@ type VitePluginDBParams =
|
|||
|
||||
export function vitePluginDb(params: VitePluginDBParams): VitePlugin {
|
||||
const srcDirPath = normalizePath(fileURLToPath(params.srcDir));
|
||||
let command: 'build' | 'serve' = 'build';
|
||||
return {
|
||||
name: 'astro:db',
|
||||
enforce: 'pre',
|
||||
configResolved(resolvedConfig) {
|
||||
command = resolvedConfig.command;
|
||||
},
|
||||
async resolveId(id, rawImporter) {
|
||||
if (id !== VIRTUAL_MODULE_ID) return;
|
||||
if (params.connectToStudio) return resolved.virtual;
|
||||
|
@ -61,6 +65,7 @@ export function vitePluginDb(params: VitePluginDBParams): VitePlugin {
|
|||
return getStudioVirtualModContents({
|
||||
appToken: params.appToken,
|
||||
tables: params.tables.get(),
|
||||
isBuild: command === 'build',
|
||||
});
|
||||
}
|
||||
return getLocalVirtualModContents({
|
||||
|
@ -135,17 +140,31 @@ ${getStringifiedCollectionExports(tables)}`;
|
|||
export function getStudioVirtualModContents({
|
||||
tables,
|
||||
appToken,
|
||||
isBuild,
|
||||
}: {
|
||||
tables: DBTables;
|
||||
appToken: string;
|
||||
isBuild: boolean;
|
||||
}) {
|
||||
function appTokenArg() {
|
||||
if(isBuild) {
|
||||
// In production build, always read the runtime environment variable.
|
||||
return 'process.env.ASTRO_STUDIO_APP_TOKEN';
|
||||
} else {
|
||||
return JSON.stringify(appToken);
|
||||
}
|
||||
}
|
||||
|
||||
function dbUrlArg() {
|
||||
const dbStr = JSON.stringify(getRemoteDatabaseUrl());
|
||||
// Allow overriding, mostly for testing
|
||||
return `import.meta.env.ASTRO_STUDIO_REMOTE_DB_URL ?? ${dbStr}`;
|
||||
}
|
||||
|
||||
return `
|
||||
import {asDrizzleTable, createRemoteDatabaseClient} from ${RUNTIME_IMPORT};
|
||||
|
||||
export const db = await createRemoteDatabaseClient(process.env.ASTRO_STUDIO_APP_TOKEN ?? ${JSON.stringify(
|
||||
appToken
|
||||
// Respect runtime env for user overrides in SSR
|
||||
)}, import.meta.env.ASTRO_STUDIO_REMOTE_DB_URL ?? ${JSON.stringify(getRemoteDatabaseUrl())});
|
||||
export const db = await createRemoteDatabaseClient(${appTokenArg()}, ${dbUrlArg()});
|
||||
|
||||
export * from ${RUNTIME_CONFIG_IMPORT};
|
||||
|
||||
|
|
|
@ -36,6 +36,10 @@ const remoteResultSchema = z.object({
|
|||
});
|
||||
|
||||
export function createRemoteDatabaseClient(appToken: string, remoteDbURL: string) {
|
||||
if(appToken == null) {
|
||||
throw new Error(`Cannot create a remote client: missing app token.`)
|
||||
}
|
||||
|
||||
const url = new URL('/db/query', remoteDbURL);
|
||||
|
||||
const db = drizzleProxy(
|
||||
|
|
|
@ -138,4 +138,29 @@ describe('astro:db', () => {
|
|||
expect($('.username').text()).to.equal('Mario');
|
||||
});
|
||||
});
|
||||
|
||||
describe('build --remote', () => {
|
||||
let remoteDbServer;
|
||||
|
||||
before(async () => {
|
||||
process.env.ASTRO_STUDIO_APP_TOKEN = 'some token';
|
||||
remoteDbServer = await setupRemoteDbServer(fixture.config);
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await remoteDbServer?.stop();
|
||||
});
|
||||
|
||||
it('Can render page', async () => {
|
||||
const app = await fixture.loadTestAdapterApp();
|
||||
const request = new Request('http://example.com/');
|
||||
const response = await app.render(request);
|
||||
const html = await response.text();
|
||||
const $ = cheerioLoad(html);
|
||||
|
||||
const ul = $('.authors-list');
|
||||
expect(ul.children()).to.have.a.lengthOf(5);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
10
packages/db/test/fixtures/no-apptoken/astro.config.ts
vendored
Normal file
10
packages/db/test/fixtures/no-apptoken/astro.config.ts
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
import db from '@astrojs/db';
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [db()],
|
||||
devToolbar: {
|
||||
enabled: false,
|
||||
},
|
||||
});
|
14
packages/db/test/fixtures/no-apptoken/db/config.ts
vendored
Normal file
14
packages/db/test/fixtures/no-apptoken/db/config.ts
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { column, defineDb, defineTable } from 'astro:db';
|
||||
|
||||
|
||||
const User = defineTable({
|
||||
columns: {
|
||||
id: column.text({ primaryKey: true, optional: false }),
|
||||
username: column.text({ optional: false, unique: true }),
|
||||
password: column.text({ optional: false }),
|
||||
},
|
||||
});
|
||||
|
||||
export default defineDb({
|
||||
tables: { User },
|
||||
});
|
4
packages/db/test/fixtures/no-apptoken/db/seed.ts
vendored
Normal file
4
packages/db/test/fixtures/no-apptoken/db/seed.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
export default function() {
|
||||
|
||||
}
|
14
packages/db/test/fixtures/no-apptoken/package.json
vendored
Normal file
14
packages/db/test/fixtures/no-apptoken/package.json
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "@test/db-no-apptoken",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/db": "workspace:*",
|
||||
"astro": "workspace:*"
|
||||
}
|
||||
}
|
15
packages/db/test/fixtures/no-apptoken/src/pages/index.astro
vendored
Normal file
15
packages/db/test/fixtures/no-apptoken/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
/// <reference path="../../.astro/db-types.d.ts" />
|
||||
import { db, User } from 'astro:db';
|
||||
|
||||
// Just for the side-effect of running all the code
|
||||
await db.select().from(User);
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
<title>Testing</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Testing</h1>
|
||||
</body>
|
||||
</html>
|
36
packages/db/test/ssr-no-apptoken.test.js
Normal file
36
packages/db/test/ssr-no-apptoken.test.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { expect } from 'chai';
|
||||
import testAdapter from '../../astro/test/test-adapter.js';
|
||||
import { loadFixture } from '../../astro/test/test-utils.js';
|
||||
import { setupRemoteDbServer } from './test-utils.js';
|
||||
|
||||
describe('missing app token', () => {
|
||||
let fixture;
|
||||
let remoteDbServer;
|
||||
before(async () => {
|
||||
fixture = await loadFixture({
|
||||
root: new URL('./fixtures/no-apptoken/', import.meta.url),
|
||||
output: 'server',
|
||||
adapter: testAdapter(),
|
||||
});
|
||||
|
||||
remoteDbServer = await setupRemoteDbServer(fixture.config);
|
||||
await fixture.build();
|
||||
// Ensure there's no token at runtime
|
||||
delete process.env.ASTRO_STUDIO_APP_TOKEN;
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await remoteDbServer?.stop();
|
||||
});
|
||||
|
||||
it('Errors as runtime', async () => {
|
||||
const app = await fixture.loadTestAdapterApp();
|
||||
const request = new Request('http://example.com/');
|
||||
try {
|
||||
const response = await app.render(request);
|
||||
await response.text();
|
||||
} catch {
|
||||
expect(response.status).to.equal(501);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -3948,6 +3948,15 @@ importers:
|
|||
specifier: workspace:*
|
||||
version: link:../../../../astro
|
||||
|
||||
packages/db/test/fixtures/no-apptoken:
|
||||
dependencies:
|
||||
'@astrojs/db':
|
||||
specifier: workspace:*
|
||||
version: link:../../..
|
||||
astro:
|
||||
specifier: workspace:*
|
||||
version: link:../../../../astro
|
||||
|
||||
packages/db/test/fixtures/no-seed:
|
||||
dependencies:
|
||||
'@astrojs/db':
|
||||
|
|
Loading…
Reference in a new issue