Compare commits

...

1 Commits

Author SHA1 Message Date
Weiko f6b5bf8bd6 fix(sdk): restore nested defineFrontComponent (create command menu items) 2026-05-27 14:33:33 +02:00
5 changed files with 38 additions and 3 deletions
@@ -51,7 +51,7 @@ import {
getInputSchemaFromSourceCode,
jsonSchemaToInputSchema,
} from 'twenty-shared/logic-function';
import { assertUnreachable } from 'twenty-shared/utils';
import { assertUnreachable, isDefined } from 'twenty-shared/utils';
const loadSources = async (appPath: string): Promise<string[]> => {
return await glob(['**/*.ts', '**/*.tsx'], {
@@ -358,7 +358,7 @@ export const buildManifest = async (
errors.push(...extract.errors);
warnings.push(...(extract.warnings ?? []));
const { component, ...rest } = extract.config;
const { component, command, ...rest } = extract.config;
const relativeFilePath = relative(appPath, filePath);
@@ -374,6 +374,14 @@ export const buildManifest = async (
frontComponents.push(config);
frontComponentsFilePaths.push(relativePath);
if (isDefined(command)) {
commandMenuItems.push({
...command,
frontComponentUniversalIdentifier: config.universalIdentifier,
} as unknown as CommandMenuItemManifest);
commandMenuItemsFilePaths.push(relativePath);
}
break;
}
case ManifestEntityKey.Views: {
@@ -19,6 +19,16 @@ export const defineFrontComponent: DefineEntity<FrontComponentConfig> = (
errors.push('Front component component must be a React component');
}
if (config.command) {
if (!config.command.universalIdentifier) {
errors.push('Command must have a universalIdentifier');
}
if (!config.command.label) {
errors.push('Command must have a label');
}
}
return createValidationResult({
config,
errors,
@@ -1,7 +1,17 @@
import { type FrontComponentManifest } from 'twenty-shared/application';
import {
type FrontComponentCommandManifest,
type FrontComponentManifest,
} from 'twenty-shared/application';
export type FrontComponentType = React.ComponentType<any>;
export type FrontComponentCommandConfig = Omit<
FrontComponentCommandManifest,
'conditionalAvailabilityExpression'
> & {
conditionalAvailabilityExpression?: boolean | string;
};
export type FrontComponentConfig = Omit<
FrontComponentManifest,
| 'sourceComponentPath'
@@ -11,4 +21,5 @@ export type FrontComponentConfig = Omit<
| 'usesSdkClient'
> & {
component: FrontComponentType;
command?: FrontComponentCommandConfig;
};
@@ -15,6 +15,11 @@ export type CommandMenuItemManifest = SyncableEntityOptions & {
conditionalAvailabilityExpression?: string;
};
export type FrontComponentCommandManifest = Omit<
CommandMenuItemManifest,
'frontComponentUniversalIdentifier'
>;
export type FrontComponentManifest = {
universalIdentifier: string;
name?: string;
@@ -34,6 +34,7 @@ export type {
} from './fieldManifestType';
export type {
CommandMenuItemManifest,
FrontComponentCommandManifest,
FrontComponentManifest,
} from './frontComponentManifestType';
export type { IndexFieldManifest } from './indexFieldManifestType';