diff --git a/apps/test-bot/commandkit.config.ts b/apps/test-bot/commandkit.config.ts index 05d14f16..b90ef5d3 100644 --- a/apps/test-bot/commandkit.config.ts +++ b/apps/test-bot/commandkit.config.ts @@ -1,15 +1,21 @@ -import { defineConfig } from 'commandkit/config'; -import { legacy } from '@commandkit/legacy'; +import { defineConfig, noBuildOnly } from 'commandkit/config'; import { i18n } from '@commandkit/i18n'; import { devtools } from '@commandkit/devtools'; import { cache } from '@commandkit/cache'; import { ai } from '@commandkit/ai'; import { tasks } from '@commandkit/tasks'; +const setup = noBuildOnly(() => { + setInterval(() => { + console.log(`Hello from ${process.pid}`); + }, 1000); +}); + +setup(); + export default defineConfig({ plugins: [ i18n(), - // legacy({ skipBuiltInValidations: true }), devtools(), cache(), ai(), diff --git a/apps/website/docs/api-reference/commandkit/functions/build-only.mdx b/apps/website/docs/api-reference/commandkit/functions/build-only.mdx new file mode 100644 index 00000000..300448f7 --- /dev/null +++ b/apps/website/docs/api-reference/commandkit/functions/build-only.mdx @@ -0,0 +1,39 @@ +--- +title: "BuildOnly" +isDefaultIndex: false +generated: true +--- + +import MemberInfo from '@site/src/components/MemberInfo'; +import GenerationInfo from '@site/src/components/GenerationInfo'; +import MemberDescription from '@site/src/components/MemberDescription'; + + + + +## buildOnly + + + +Creates a function from the given function that runs only in build mode. + + + +*Example* + +```ts +const buildOnlyFn = buildOnly(() => { + console.log('This function runs only in build mode'); +}); +buildOnlyFn(); // This will log the message only in build mode +``` + +```ts title="Signature" +function buildOnly any>(fn: T): T +``` +Parameters + +### fn + + + diff --git a/apps/website/docs/api-reference/commandkit/functions/create-proxy.mdx b/apps/website/docs/api-reference/commandkit/functions/create-proxy.mdx index f050d3aa..08206009 100644 --- a/apps/website/docs/api-reference/commandkit/functions/create-proxy.mdx +++ b/apps/website/docs/api-reference/commandkit/functions/create-proxy.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## createProxy - + Creates a simple proxy object that mirrors the target object. diff --git a/apps/website/docs/api-reference/commandkit/functions/debounce.mdx b/apps/website/docs/api-reference/commandkit/functions/debounce.mdx index 6fade3b4..e90a1eb1 100644 --- a/apps/website/docs/api-reference/commandkit/functions/debounce.mdx +++ b/apps/website/docs/api-reference/commandkit/functions/debounce.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## debounce - + Debounces a function. diff --git a/apps/website/docs/api-reference/commandkit/functions/defer.mdx b/apps/website/docs/api-reference/commandkit/functions/defer.mdx index 6005df9e..0b8d627d 100644 --- a/apps/website/docs/api-reference/commandkit/functions/defer.mdx +++ b/apps/website/docs/api-reference/commandkit/functions/defer.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## defer - + Defers the execution of a function. diff --git a/apps/website/docs/api-reference/commandkit/functions/dev-only.mdx b/apps/website/docs/api-reference/commandkit/functions/dev-only.mdx index 9b3896b1..c3c9bf65 100644 --- a/apps/website/docs/api-reference/commandkit/functions/dev-only.mdx +++ b/apps/website/docs/api-reference/commandkit/functions/dev-only.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## devOnly - + Creates a function from the given function that runs only in development mode. diff --git a/apps/website/docs/api-reference/commandkit/functions/find-app-directory.mdx b/apps/website/docs/api-reference/commandkit/functions/find-app-directory.mdx index e5c4a8f2..a802237d 100644 --- a/apps/website/docs/api-reference/commandkit/functions/find-app-directory.mdx +++ b/apps/website/docs/api-reference/commandkit/functions/find-app-directory.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## findAppDirectory - + Returns the path to the app directory. diff --git a/apps/website/docs/api-reference/commandkit/functions/get-current-directory.mdx b/apps/website/docs/api-reference/commandkit/functions/get-current-directory.mdx index 7e97f24a..344110cf 100644 --- a/apps/website/docs/api-reference/commandkit/functions/get-current-directory.mdx +++ b/apps/website/docs/api-reference/commandkit/functions/get-current-directory.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## getCurrentDirectory - + Returns the current working directory of the CommandKit application. This is typically the directory where the source code is located. diff --git a/apps/website/docs/api-reference/commandkit/functions/get-source-directories.mdx b/apps/website/docs/api-reference/commandkit/functions/get-source-directories.mdx index 269fb66c..279fa99e 100644 --- a/apps/website/docs/api-reference/commandkit/functions/get-source-directories.mdx +++ b/apps/website/docs/api-reference/commandkit/functions/get-source-directories.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## getSourceDirectories - + Returns the possible source directories for the CommandKit application. This includes the `src`, `.commandkit`, and the distribution directory. diff --git a/apps/website/docs/api-reference/commandkit/functions/json-serialize.mdx b/apps/website/docs/api-reference/commandkit/functions/json-serialize.mdx index b76aa015..69780f82 100644 --- a/apps/website/docs/api-reference/commandkit/functions/json-serialize.mdx +++ b/apps/website/docs/api-reference/commandkit/functions/json-serialize.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## JsonSerialize - + Serializes a value to JSON. diff --git a/apps/website/docs/api-reference/commandkit/functions/no-build-only.mdx b/apps/website/docs/api-reference/commandkit/functions/no-build-only.mdx new file mode 100644 index 00000000..2c9af655 --- /dev/null +++ b/apps/website/docs/api-reference/commandkit/functions/no-build-only.mdx @@ -0,0 +1,39 @@ +--- +title: "NoBuildOnly" +isDefaultIndex: false +generated: true +--- + +import MemberInfo from '@site/src/components/MemberInfo'; +import GenerationInfo from '@site/src/components/GenerationInfo'; +import MemberDescription from '@site/src/components/MemberDescription'; + + + + +## noBuildOnly + + + +Creates a function from the given function that runs only outside of build mode. + + + +*Example* + +```ts +const noBuildOnlyFn = noBuildOnly(() => { + console.log('This function runs only outside of build mode'); +}); +noBuildOnlyFn(); // This will log the message only outside of build mode +``` + +```ts title="Signature" +function noBuildOnly any>(fn: T): T +``` +Parameters + +### fn + + + diff --git a/apps/website/docs/api-reference/commandkit/interfaces/simple-proxy.mdx b/apps/website/docs/api-reference/commandkit/interfaces/simple-proxy.mdx index dc55483c..979f81c5 100644 --- a/apps/website/docs/api-reference/commandkit/interfaces/simple-proxy.mdx +++ b/apps/website/docs/api-reference/commandkit/interfaces/simple-proxy.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## SimpleProxy - + Represents a simple proxy object that mirrors a target object. diff --git a/apps/website/docs/api-reference/commandkit/types/hmrevent-type.mdx b/apps/website/docs/api-reference/commandkit/types/hmrevent-type.mdx index d42b1534..de039772 100644 --- a/apps/website/docs/api-reference/commandkit/types/hmrevent-type.mdx +++ b/apps/website/docs/api-reference/commandkit/types/hmrevent-type.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## HMREventType - + The type for HMR events. diff --git a/apps/website/docs/api-reference/commandkit/variables/commandkit_bootstrap_mode.mdx b/apps/website/docs/api-reference/commandkit/variables/commandkit_bootstrap_mode.mdx index c058b3f5..a608ca7d 100644 --- a/apps/website/docs/api-reference/commandkit/variables/commandkit_bootstrap_mode.mdx +++ b/apps/website/docs/api-reference/commandkit/variables/commandkit_bootstrap_mode.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## COMMANDKIT_BOOTSTRAP_MODE - + The current bootstrap mode of CommandKit. This can be 'development' or 'production'. diff --git a/apps/website/docs/api-reference/commandkit/variables/hmrevent-type.mdx b/apps/website/docs/api-reference/commandkit/variables/hmrevent-type.mdx index 36b58698..f8ac7bb1 100644 --- a/apps/website/docs/api-reference/commandkit/variables/hmrevent-type.mdx +++ b/apps/website/docs/api-reference/commandkit/variables/hmrevent-type.mdx @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription'; ## HMREventType - + Types of Hot Module Replacement events diff --git a/apps/website/docs/guide/05-official-plugins/08-commandkit-tasks.mdx b/apps/website/docs/guide/05-official-plugins/08-commandkit-tasks.mdx index a19c2778..ed840a3a 100644 --- a/apps/website/docs/guide/05-official-plugins/08-commandkit-tasks.mdx +++ b/apps/website/docs/guide/05-official-plugins/08-commandkit-tasks.mdx @@ -130,30 +130,42 @@ const driver = new BullMQDriver({ ### Environment-specific configuration ```ts +import { COMMANDKIT_IS_DEV } from 'commandkit'; +import { defineConfig, noBuildOnly } from 'commandkit/config'; import { tasks } from '@commandkit/tasks'; import { SQLiteDriver } from '@commandkit/tasks/sqlite'; import { BullMQDriver } from '@commandkit/tasks/bullmq'; import { setDriver } from '@commandkit/tasks'; -import { COMMANDKIT_IS_DEV } from 'commandkit'; -// Choose driver based on environment -if (COMMANDKIT_IS_DEV) { - setDriver(new SQLiteDriver('./tasks.db')); -} else { - setDriver( - new BullMQDriver({ - host: process.env.REDIS_HOST || 'localhost', - port: parseInt(process.env.REDIS_PORT || '6379'), - password: process.env.REDIS_PASSWORD, - }), - ); -} +// set up the driver in non-build processes only +const setupDriver = noBuildOnly(() => { + // Choose driver based on environment + if (COMMANDKIT_IS_DEV) { + setDriver(new SQLiteDriver('./tasks.db')); + } else { + setDriver( + new BullMQDriver({ + host: process.env.REDIS_HOST || 'localhost', + port: parseInt(process.env.REDIS_PORT || '6379'), + password: process.env.REDIS_PASSWORD, + }), + ); + } +}); + +setupDriver(); -export default { +export default defineConfig({ plugins: [tasks()], -}; +}); ``` +:::warning +Avoid loading the code that keeps the event loop alive inside the build process. +Otherwise the build command will never exit. Use the helper functions such as `buildOnly()` or `noBuildOnly()` +to conditionally load the code in appropriate places. +::: + ## Creating your first task Create a file in `src/app/tasks/` to define your tasks: diff --git a/packages/commandkit/config.cjs b/packages/commandkit/config.cjs index c14b2d66..76bdc6eb 100644 --- a/packages/commandkit/config.cjs +++ b/packages/commandkit/config.cjs @@ -1,5 +1,8 @@ const { defineConfig } = require('./dist/config/config.js'); +const { buildOnly, noBuildOnly } = require('./dist/utils/utilities.js'); module.exports = { defineConfig, + buildOnly, + noBuildOnly, }; diff --git a/packages/commandkit/config.d.ts b/packages/commandkit/config.d.ts index ac4bc397..275e9f1e 100644 --- a/packages/commandkit/config.d.ts +++ b/packages/commandkit/config.d.ts @@ -1 +1,2 @@ export { defineConfig, CommandKitConfiguration as Config } from './dist/index'; +export { buildOnly, noBuildOnly } from './dist/utils/utilities'; diff --git a/packages/commandkit/src/cli/development.ts b/packages/commandkit/src/cli/development.ts index 1c27060e..10130094 100644 --- a/packages/commandkit/src/cli/development.ts +++ b/packages/commandkit/src/cli/development.ts @@ -54,6 +54,7 @@ const isEventSource = (p: string) => */ export async function bootstrapDevelopmentServer(configPath?: string) { process.env.COMMANDKIT_BOOTSTRAP_MODE = 'development'; + process.env.COMMANDKIT_INTERNAL_IS_CLI_PROCESS = 'true'; const start = performance.now(); const cwd = configPath || COMMANDKIT_CWD; const configPaths = getPossibleConfigPaths(cwd); diff --git a/packages/commandkit/src/cli/env.ts b/packages/commandkit/src/cli/env.ts index cd4cf96e..9c6c039a 100644 --- a/packages/commandkit/src/cli/env.ts +++ b/packages/commandkit/src/cli/env.ts @@ -6,6 +6,8 @@ export function DevEnv(_static = false) { const common = { NODE_ENV: 'development', COMMANDKIT_IS_DEV: 'true', + COMMANDKIT_INTERNAL_IS_CLI_PROCESS: 'false', + COMMANDKIT_IS_BUILD: 'false', }; if (_static) return Object.assign({}, common); @@ -21,6 +23,8 @@ export function ProdEnv(_static = false) { const common = { NODE_ENV: 'production', COMMANDKIT_IS_DEV: 'false', + COMMANDKIT_INTERNAL_IS_CLI_PROCESS: 'false', + COMMANDKIT_IS_BUILD: 'false', }; if (_static) return Object.assign({}, common); diff --git a/packages/commandkit/src/cli/production.ts b/packages/commandkit/src/cli/production.ts index b78472e2..cb1ed460 100644 --- a/packages/commandkit/src/cli/production.ts +++ b/packages/commandkit/src/cli/production.ts @@ -32,6 +32,8 @@ export async function bootstrapProductionServer(configPath?: string) { */ export async function createProductionBuild(configPath?: string) { process.env.COMMANDKIT_BOOTSTRAP_MODE = 'production'; + process.env.COMMANDKIT_INTERNAL_IS_CLI_PROCESS = 'true'; + process.env.COMMANDKIT_IS_BUILD ??= 'true'; const cwd = configPath || COMMANDKIT_CWD; const config = await loadConfigFile(cwd); diff --git a/packages/commandkit/src/utils/constants.ts b/packages/commandkit/src/utils/constants.ts index a71b06d8..cd613298 100644 --- a/packages/commandkit/src/utils/constants.ts +++ b/packages/commandkit/src/utils/constants.ts @@ -18,6 +18,18 @@ export const COMMANDKIT_IS_CLI = process.env.COMMANDKIT_IS_CLI === 'true'; */ export const COMMANDKIT_IS_TEST = process.env.COMMANDKIT_IS_TEST === 'true'; +/** + * Indicates that CommandKit is running in a build-like environment. + * @private + * @internal + */ +export function isBuildLikeEnvironment() { + const isCLI = process.env.COMMANDKIT_INTERNAL_IS_CLI_PROCESS === 'true'; + if (isCLI) return true; + + return process.env.COMMANDKIT_IS_BUILD === 'true'; +} + /** * The current bootstrap mode of CommandKit. * This can be 'development' or 'production'. diff --git a/packages/commandkit/src/utils/utilities.ts b/packages/commandkit/src/utils/utilities.ts index 7f930eec..c5a7b7bc 100644 --- a/packages/commandkit/src/utils/utilities.ts +++ b/packages/commandkit/src/utils/utilities.ts @@ -4,6 +4,7 @@ import { COMMANDKIT_CWD, COMMANDKIT_IS_CLI, COMMANDKIT_IS_DEV, + isBuildLikeEnvironment, } from './constants'; import { getConfig } from '../config/config'; @@ -169,6 +170,50 @@ export function devOnly any>(fn: T): T { return f as T; } +/** + * Creates a function from the given function that runs only in build mode. + * @param fn The function to run in build mode. + * @returns The function that runs only in build mode. + * @example + * ```ts + * const buildOnlyFn = buildOnly(() => { + * console.log('This function runs only in build mode'); + * }); + * buildOnlyFn(); // This will log the message only in build mode + * ``` + */ +export function buildOnly any>(fn: T): T { + const f = (...args: Parameters) => { + if (isBuildLikeEnvironment()) { + return fn(...args); + } + }; + + return f as T; +} + +/** + * Creates a function from the given function that runs only outside of build mode. + * @param fn The function to run outside of build mode. + * @returns The function that runs only outside of build mode. + * @example + * ```ts + * const noBuildOnlyFn = noBuildOnly(() => { + * console.log('This function runs only outside of build mode'); + * }); + * noBuildOnlyFn(); // This will log the message only outside of build mode + * ``` + */ +export function noBuildOnly any>(fn: T): T { + const f = (...args: Parameters) => { + if (!isBuildLikeEnvironment()) { + return fn(...args); + } + }; + + return f as T; +} + /** * Represents a simple proxy object that mirrors a target object. */