summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Matt Kane <m@mk.gg> 2024-10-04 15:12:44 +0100
committerGravatar Matt Kane <m@mk.gg> 2024-10-04 15:12:44 +0100
commit953e6e0f23a1121b1137ca67e675ce9f539ed549 (patch)
treef99789a70c1fbb6f64916d3a8670514a09536570
parent423dfc19ad83661b71151f8cec40701c7ced557b (diff)
parent6e1dfeb76bec09d24928bab798c6ad3280f42e84 (diff)
downloadastro-953e6e0f23a1121b1137ca67e675ce9f539ed549.tar.gz
astro-953e6e0f23a1121b1137ca67e675ce9f539ed549.tar.zst
astro-953e6e0f23a1121b1137ca67e675ce9f539ed549.zip
Merge branch 'main' into next
-rw-r--r--.changeset/ninety-monkeys-complain.md5
-rw-r--r--.changeset/swift-snakes-hope.md5
-rw-r--r--packages/astro/src/actions/runtime/virtual/get-action.ts5
-rw-r--r--packages/astro/src/content/content-layer.ts18
-rw-r--r--packages/astro/templates/actions.mjs6
-rw-r--r--packages/astro/test/actions.test.js35
-rw-r--r--packages/astro/test/fixtures/actions/src/actions/index.ts24
7 files changed, 94 insertions, 4 deletions
diff --git a/.changeset/ninety-monkeys-complain.md b/.changeset/ninety-monkeys-complain.md
new file mode 100644
index 000000000..c8a06da1f
--- /dev/null
+++ b/.changeset/ninety-monkeys-complain.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Clear content layer cache when astro version changes
diff --git a/.changeset/swift-snakes-hope.md b/.changeset/swift-snakes-hope.md
new file mode 100644
index 000000000..34c626b39
--- /dev/null
+++ b/.changeset/swift-snakes-hope.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Allows special characters in Action names
diff --git a/packages/astro/src/actions/runtime/virtual/get-action.ts b/packages/astro/src/actions/runtime/virtual/get-action.ts
index b547b57c1..59db34cbc 100644
--- a/packages/astro/src/actions/runtime/virtual/get-action.ts
+++ b/packages/astro/src/actions/runtime/virtual/get-action.ts
@@ -11,7 +11,10 @@ import type { ActionAccept, ActionClient } from './server.js';
export async function getAction(
path: string,
): Promise<ActionClient<unknown, ActionAccept, ZodType>> {
- const pathKeys = path.replace('/_actions/', '').split('.');
+ const pathKeys = path
+ .replace('/_actions/', '')
+ .split('.')
+ .map((key) => decodeURIComponent(key));
// @ts-expect-error virtual module
let { server: actionLookup } = await import('astro:internal-actions');
diff --git a/packages/astro/src/content/content-layer.ts b/packages/astro/src/content/content-layer.ts
index dcb7aca9f..df67d49a8 100644
--- a/packages/astro/src/content/content-layer.ts
+++ b/packages/astro/src/content/content-layer.ts
@@ -146,13 +146,27 @@ export class ContentLayer {
const { digest: currentConfigDigest } = contentConfig.config;
this.#lastConfigDigest = currentConfigDigest;
+ let shouldClear = false;
const previousConfigDigest = await this.#store.metaStore().get('config-digest');
+ const previousAstroVersion = await this.#store.metaStore().get('astro-version');
if (currentConfigDigest && previousConfigDigest !== currentConfigDigest) {
- logger.info('Content config changed, clearing cache');
+ logger.info('Content config changed');
+ shouldClear = true;
+ }
+ if (process.env.ASTRO_VERSION && previousAstroVersion !== process.env.ASTRO_VERSION) {
+ logger.info('Astro version changed');
+ shouldClear = true;
+ }
+ if (shouldClear) {
+ logger.info('Clearing content store');
this.#store.clearAll();
+ }
+ if (process.env.ASTRO_VERSION) {
+ await this.#store.metaStore().set('astro-version', process.env.ASTRO_VERSION);
+ }
+ if (currentConfigDigest) {
await this.#store.metaStore().set('config-digest', currentConfigDigest);
}
-
await Promise.all(
Object.entries(contentConfig.config.collections).map(async ([name, collection]) => {
if (collection.type !== CONTENT_LAYER_TYPE) {
diff --git a/packages/astro/templates/actions.mjs b/packages/astro/templates/actions.mjs
index 3ff65cecf..b83cc4a39 100644
--- a/packages/astro/templates/actions.mjs
+++ b/packages/astro/templates/actions.mjs
@@ -5,13 +5,17 @@ import {
getActionQueryString,
} from 'astro:actions';
+const ENCODED_DOT = '%2E';
+
function toActionProxy(actionCallback = {}, aggregatedPath = '') {
return new Proxy(actionCallback, {
get(target, objKey) {
if (objKey in target || typeof objKey === 'symbol') {
return target[objKey];
}
- const path = aggregatedPath + objKey.toString();
+ // Add the key, encoding dots so they're not interpreted as nested properties.
+ const path =
+ aggregatedPath + encodeURIComponent(objKey.toString()).replaceAll('.', ENCODED_DOT);
function action(param) {
return handleAction(param, path, this);
}
diff --git a/packages/astro/test/actions.test.js b/packages/astro/test/actions.test.js
index 17758e82c..793e6ebe7 100644
--- a/packages/astro/test/actions.test.js
+++ b/packages/astro/test/actions.test.js
@@ -115,6 +115,23 @@ describe('Astro Actions', () => {
assert.equal(data.success, true);
assert.equal(data.isFormData, true, 'Should receive plain FormData');
});
+
+ it('Handles special characters in action names', async () => {
+ for (const name of ['with%2Fslash', 'with%20space', 'with%2Edot']) {
+ const res = await fixture.fetch(`/_actions/${name}`, {
+ method: 'POST',
+ body: JSON.stringify({ name: 'ben' }),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ assert.equal(res.ok, true);
+ const text = await res.text();
+ assert.equal(res.headers.get('Content-Type'), 'application/json+devalue');
+ const data = devalue.parse(text);
+ assert.equal(data, 'Hello, ben!');
+ }
+ });
});
describe('build', () => {
@@ -428,6 +445,24 @@ describe('Astro Actions', () => {
const dataRest = devalue.parse(await resRest.text());
assert.equal('fake', dataRest?.uploadId);
});
+
+ it('Handles special characters in action names', async () => {
+ for (const name of ['with%2Fslash', 'with%20space', 'with%2Edot']) {
+ const req = new Request(`http://example.com/_actions/${name}`, {
+ method: 'POST',
+ body: JSON.stringify({ name: 'ben' }),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ const res = await app.render(req);
+ assert.equal(res.ok, true);
+ const text = await res.text();
+ assert.equal(res.headers.get('Content-Type'), 'application/json+devalue');
+ const data = devalue.parse(text);
+ assert.equal(data, 'Hello, ben!');
+ }
+ });
});
});
diff --git a/packages/astro/test/fixtures/actions/src/actions/index.ts b/packages/astro/test/fixtures/actions/src/actions/index.ts
index 4e6120309..78cc39620 100644
--- a/packages/astro/test/fixtures/actions/src/actions/index.ts
+++ b/packages/astro/test/fixtures/actions/src/actions/index.ts
@@ -161,4 +161,28 @@ export const server = {
};
},
}),
+ "with.dot": defineAction({
+ input: z.object({
+ name: z.string(),
+ }),
+ handler: async (input) => {
+ return `Hello, ${input.name}!`
+ }
+ }),
+ "with space": defineAction({
+ input: z.object({
+ name: z.string(),
+ }),
+ handler: async (input) => {
+ return `Hello, ${input.name}!`
+ }
+ }),
+ "with/slash": defineAction({
+ input: z.object({
+ name: z.string(),
+ }),
+ handler: async (input) => {
+ return `Hello, ${input.name}!`
+ }
+ }),
};