mirror of
https://github.com/withastro/astro.git
synced 2025-03-24 23:21:57 -05:00
fix(actions): resolve actions when there aren't user actions (#11525)
* fix(actions): pass path as input * revert code * chore: apply suggestions
This commit is contained in:
parent
dfbca06dda
commit
80681318c6
5 changed files with 68 additions and 10 deletions
5
.changeset/new-melons-cross.md
Normal file
5
.changeset/new-melons-cross.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fixes a case where the build was failing when `experimental.actions` was enabled, an adapter was in use, and there were not actions inside the user code base.
|
|
@ -1,3 +1,6 @@
|
|||
export const VIRTUAL_MODULE_ID = 'astro:actions';
|
||||
export const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID;
|
||||
export const ACTIONS_TYPES_FILE = 'actions.d.ts';
|
||||
export const VIRTUAL_INTERNAL_MODULE_ID = 'astro:internal-actions';
|
||||
export const RESOLVED_VIRTUAL_INTERNAL_MODULE_ID = '\0astro:internal-actions';
|
||||
export const NOOP_ACTIONS = '\0noop-actions';
|
||||
|
|
|
@ -1,12 +1,25 @@
|
|||
import fsMod from 'node:fs';
|
||||
import type { Plugin as VitePlugin } from 'vite';
|
||||
import type { AstroIntegration } from '../@types/astro.js';
|
||||
import type { AstroIntegration, AstroSettings } from '../@types/astro.js';
|
||||
import { ActionsWithoutServerOutputError } from '../core/errors/errors-data.js';
|
||||
import { AstroError } from '../core/errors/errors.js';
|
||||
import { isServerLikeOutput, viteID } from '../core/util.js';
|
||||
import { ACTIONS_TYPES_FILE, RESOLVED_VIRTUAL_MODULE_ID, VIRTUAL_MODULE_ID } from './consts.js';
|
||||
import {
|
||||
ACTIONS_TYPES_FILE,
|
||||
NOOP_ACTIONS,
|
||||
RESOLVED_VIRTUAL_INTERNAL_MODULE_ID,
|
||||
RESOLVED_VIRTUAL_MODULE_ID,
|
||||
VIRTUAL_INTERNAL_MODULE_ID,
|
||||
VIRTUAL_MODULE_ID,
|
||||
} from './consts.js';
|
||||
|
||||
export default function astroActions({ fs = fsMod }: { fs?: typeof fsMod }): AstroIntegration {
|
||||
export default function astroActions({
|
||||
fs = fsMod,
|
||||
settings,
|
||||
}: {
|
||||
fs?: typeof fsMod;
|
||||
settings: AstroSettings;
|
||||
}): AstroIntegration {
|
||||
return {
|
||||
name: VIRTUAL_MODULE_ID,
|
||||
hooks: {
|
||||
|
@ -22,10 +35,7 @@ export default function astroActions({ fs = fsMod }: { fs?: typeof fsMod }): Ast
|
|||
);
|
||||
params.updateConfig({
|
||||
vite: {
|
||||
define: {
|
||||
'import.meta.env.ACTIONS_PATH': stringifiedActionsImport,
|
||||
},
|
||||
plugins: [vitePluginActions(fs)],
|
||||
plugins: [vitePluginUserActions({ settings }), vitePluginActions(fs)],
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -50,6 +60,42 @@ export default function astroActions({ fs = fsMod }: { fs?: typeof fsMod }): Ast
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This plugin is responsible to load the known file `actions/index.js` / `actions.js`
|
||||
* If the file doesn't exist, it returns an empty object.
|
||||
* @param settings
|
||||
*/
|
||||
export function vitePluginUserActions({ settings }: { settings: AstroSettings }): VitePlugin {
|
||||
let resolvedActionsId: string;
|
||||
return {
|
||||
name: '@astro/plugin-actions',
|
||||
async resolveId(id) {
|
||||
if (id === NOOP_ACTIONS) {
|
||||
return NOOP_ACTIONS;
|
||||
}
|
||||
if (id === VIRTUAL_INTERNAL_MODULE_ID) {
|
||||
const resolvedModule = await this.resolve(
|
||||
`${decodeURI(new URL('actions', settings.config.srcDir).pathname)}`
|
||||
);
|
||||
|
||||
if (!resolvedModule) {
|
||||
return NOOP_ACTIONS;
|
||||
}
|
||||
resolvedActionsId = resolvedModule.id;
|
||||
return RESOLVED_VIRTUAL_INTERNAL_MODULE_ID;
|
||||
}
|
||||
},
|
||||
|
||||
load(id) {
|
||||
if (id === NOOP_ACTIONS) {
|
||||
return 'export const server = {}';
|
||||
} else if (id === RESOLVED_VIRTUAL_INTERNAL_MODULE_ID) {
|
||||
return `export { server } from '${resolvedActionsId}';`;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const vitePluginActions = (fs: typeof fsMod): VitePlugin => ({
|
||||
name: VIRTUAL_MODULE_ID,
|
||||
enforce: 'pre',
|
||||
|
|
|
@ -12,14 +12,16 @@ export type MaybePromise<T> = T | Promise<T>;
|
|||
|
||||
/**
|
||||
* Get server-side action based on the route path.
|
||||
* Imports from `import.meta.env.ACTIONS_PATH`, which maps to
|
||||
* Imports from the virtual module `astro:internal-actions`, which maps to
|
||||
* the user's `src/actions/index.ts` file at build-time.
|
||||
*/
|
||||
export async function getAction(
|
||||
path: string
|
||||
): Promise<((param: unknown) => MaybePromise<unknown>) | undefined> {
|
||||
const pathKeys = path.replace('/_actions/', '').split('.');
|
||||
let { server: actionLookup } = await import(import.meta.env.ACTIONS_PATH);
|
||||
// @ts-expect-error virtual module
|
||||
let { server: actionLookup } = await import('astro:internal-actions');
|
||||
|
||||
for (const key of pathKeys) {
|
||||
if (!(key in actionLookup)) {
|
||||
return undefined;
|
||||
|
|
|
@ -119,7 +119,7 @@ export async function runHookConfigSetup({
|
|||
}
|
||||
if (settings.config.experimental?.actions) {
|
||||
const { default: actionsIntegration } = await import('../actions/index.js');
|
||||
settings.config.integrations.push(actionsIntegration({ fs }));
|
||||
settings.config.integrations.push(actionsIntegration({ fs, settings }));
|
||||
}
|
||||
|
||||
let updatedConfig: AstroConfig = { ...settings.config };
|
||||
|
@ -230,9 +230,11 @@ export async function runHookConfigSetup({
|
|||
const exts = (input.flat(Infinity) as string[]).map((ext) => `.${ext.replace(/^\./, '')}`);
|
||||
updatedSettings.pageExtensions.push(...exts);
|
||||
}
|
||||
|
||||
function addContentEntryType(contentEntryType: ContentEntryType) {
|
||||
updatedSettings.contentEntryTypes.push(contentEntryType);
|
||||
}
|
||||
|
||||
function addDataEntryType(dataEntryType: DataEntryType) {
|
||||
updatedSettings.dataEntryTypes.push(dataEntryType);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue