@kellanjs/actioncraft
Version:
Fluent, type-safe builder for Next.js server actions.
62 lines • 2.41 kB
JavaScript
import { Crafter } from "./classes/crafter.js";
import { Executor } from "./classes/executor.js";
/**
* One of two entry points to the Actioncraft system.
* It provides you with an empty Crafter instance on which you can call any of the fluent
* Crafter methods to configure and define your action.
*
* Example Usage:
* ```ts
* const myAction = craft(async (action) => {
* return action
* .config(...)
* .schemas(...)
* .errors(...)
* .handler(...)
* .callbacks(...)
* });
* ```
*
* @param craftFn - The function that the user passes to `craft()` in order to build an action.
* @returns The fully-typed server action function that can be used in your app.
*/
export function craft(craftFn) {
const crafter = craftFn(new Crafter({}, {}, {}, {}, undefined));
// Handle async crafter functions
if (crafter instanceof Promise) {
return _craftAsync(crafter);
}
// Handle sync crafter functions
const executor = new Executor(crafter);
const craftedAction = executor.craft();
return craftedAction;
}
/**
* Internal helper function to handle async craft functions.
* Encapsulates the logic for creating async actions and preserving metadata.
*/
function _craftAsync(crafterPromise) {
// Resolve the crafter once and cache the resulting action to ensure consistent IDs
const actionPromise = crafterPromise.then((resolvedCrafter) => {
const executor = new Executor(resolvedCrafter);
return executor.craft();
});
// For async craft functions, we need to return an async action
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const asyncAction = (async (...args) => {
// Wait for the cached action to be ready
const craftedAction = await actionPromise;
// Call the action with the user's arguments
return craftedAction(...args);
});
// We need to preserve the config and ID for the initial() function to work
// We'll use the same cached action to ensure consistent metadata
actionPromise.then((craftedAction) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
asyncAction.__ac_config = craftedAction.__ac_config;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
asyncAction.__ac_id = craftedAction.__ac_id;
});
return asyncAction;
}
//# sourceMappingURL=craft.js.map