Skip to content

Commit a4e793d

Browse files
adrians5jCopilot
andauthored
feat: add render prop for compound exts (#4902)
Co-authored-by: Copilot <[email protected]> Co-authored-by: adrians5j <[email protected]>
1 parent 86c21b4 commit a4e793d

File tree

26 files changed

+314
-200
lines changed

26 files changed

+314
-200
lines changed

extensions/MyApiKey.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ class MyApiKeyImpl implements ApiKeyFactory.Interface {
1313
}
1414
}
1515

16-
const MyApiKey = ApiKeyFactory.createImplementation({
16+
export default ApiKeyFactory.createImplementation({
1717
implementation: MyApiKeyImpl,
1818
dependencies: []
1919
});
20-
21-
export default MyApiKey;

extensions/graphql/MyGraphQLSchema.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ class Schema implements GraphQLSchemaFactory.Interface {
2525
}
2626
}
2727

28-
const MyGraphQLSchema = GraphQLSchemaFactory.createImplementation({
28+
export default GraphQLSchemaFactory.createImplementation({
2929
implementation: Schema,
3030
dependencies: [IdentityContext]
3131
});
32-
33-
export default MyGraphQLSchema;

packages/auth0/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
"mobx": "^6.15.0",
2525
"mobx-react-lite": "^3.4.3",
2626
"react": "18.2.0",
27-
"react-dom": "18.2.0"
27+
"react-dom": "18.2.0",
28+
"zod": "^3.25.76"
2829
},
2930
"devDependencies": {
3031
"@types/jsonwebtoken": "^9.0.10",

packages/auth0/src/Auth0.tsx

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,37 @@
11
import React from "react";
2+
import { defineExtension } from "@webiny/project/defineExtension/index.js";
23
import { EnvVar } from "@webiny/project/extensions/index.js";
34
import { Api, Admin } from "@webiny/project-aws";
5+
import { z } from "zod";
46

5-
interface Auth0Props {
6-
issuer: string;
7-
clientId: string;
8-
apiConfig: string;
9-
}
10-
11-
export const Auth0 = (props: Auth0Props) => {
12-
return (
13-
<>
14-
{/* Lambda vars */}
15-
<EnvVar varName={"AUTH0_ISSUER"} value={props.issuer} />
16-
<EnvVar varName={"AUTH0_CLIENT_ID"} value={props.clientId} />
17-
{/* Admin app vars */}
18-
<EnvVar varName={"REACT_APP_IDP_TYPE"} value={"auth0"} />
19-
<EnvVar varName={"REACT_APP_AUTH0_ISSUER"} value={props.issuer} />
20-
<EnvVar varName={"REACT_APP_AUTH0_CLIENT_ID"} value={props.clientId} />
21-
{/* Api extensions */}
22-
<Api.Extension
23-
src={import.meta.dirname + "/api/features/Auth0Idp/feature.js"}
24-
exportName={"Auth0IdpFeature"}
25-
/>
26-
<Api.Extension src={props.apiConfig} />
27-
{/* Admin extensions */}
28-
<Admin.Extension src={import.meta.dirname + "/admin/Extension.js"} />
29-
</>
30-
);
31-
};
7+
export const Auth0 = defineExtension({
8+
type: "Project/Auth0",
9+
tags: { runtimeContext: "project" },
10+
description: "Enable and configure Auth0 authentication.",
11+
paramsSchema: z.object({
12+
issuer: z.string().describe("Auth0 issuer URL."),
13+
clientId: z.string().describe("Auth0 client ID."),
14+
apiConfig: z.string().describe("Path to API configuration.")
15+
}),
16+
render: props => {
17+
return (
18+
<>
19+
{/* Lambda vars */}
20+
<EnvVar varName={"AUTH0_ISSUER"} value={props.issuer} />
21+
<EnvVar varName={"AUTH0_CLIENT_ID"} value={props.clientId} />
22+
{/* Admin app vars */}
23+
<EnvVar varName={"REACT_APP_IDP_TYPE"} value={"auth0"} />
24+
<EnvVar varName={"REACT_APP_AUTH0_ISSUER"} value={props.issuer} />
25+
<EnvVar varName={"REACT_APP_AUTH0_CLIENT_ID"} value={props.clientId} />
26+
{/* Api extensions */}
27+
<Api.Extension
28+
src={import.meta.dirname + "/api/features/Auth0Idp/feature.js"}
29+
exportName={"Auth0IdpFeature"}
30+
/>
31+
<Api.Extension src={props.apiConfig} />
32+
{/* Admin extensions */}
33+
<Admin.Extension src={import.meta.dirname + "/admin/Extension.js"} />
34+
</>
35+
);
36+
}
37+
});

packages/cli/files/references.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

packages/cognito/src/Cognito.tsx

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
import React from "react";
2+
import { defineExtension } from "@webiny/project/defineExtension/index.js";
23
import { EnvVar } from "@webiny/project/extensions/index.js";
34
import { Api, Admin } from "@webiny/project-aws";
5+
import { z } from "zod";
46

5-
export interface CognitoProps {
6-
apiConfig?: string;
7-
}
8-
9-
export const Cognito = (props: CognitoProps) => {
10-
return (
11-
<>
12-
<EnvVar varName={"REACT_APP_IDP_TYPE"} value={"cognito"} />
13-
{/* Api extensions */}
14-
<Api.Extension
15-
src={import.meta.dirname + "/api/CognitoApiFeature.js"}
16-
exportName={"CognitoApiFeature"}
17-
/>
18-
{props.apiConfig ? <Api.Extension src={props.apiConfig} /> : null}
19-
{/* Admin extensions */}
20-
<Admin.Extension src={import.meta.dirname + "/admin/Extension.js"} />
21-
</>
22-
);
23-
};
7+
export const Cognito = defineExtension({
8+
type: "Project/Cognito",
9+
tags: { runtimeContext: "project" },
10+
description: "Enable and configure Cognito authentication.",
11+
paramsSchema: z.object({
12+
apiConfig: z.string().describe("Path to API configuration.").optional()
13+
}),
14+
render: props => {
15+
return (
16+
<>
17+
<EnvVar varName={"REACT_APP_IDP_TYPE"} value={"cognito"} />
18+
{/* Api extensions */}
19+
<Api.Extension
20+
src={import.meta.dirname + "/api/CognitoApiFeature.js"}
21+
exportName={"CognitoApiFeature"}
22+
/>
23+
{props.apiConfig ? <Api.Extension src={props.apiConfig} /> : null}
24+
{/* Admin extensions */}
25+
<Admin.Extension src={import.meta.dirname + "/admin/Extension.js"} />
26+
</>
27+
);
28+
}
29+
});

packages/okta/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
"mobx": "^6.15.0",
2525
"mobx-react-lite": "^3.4.3",
2626
"react": "18.2.0",
27-
"react-dom": "18.2.0"
27+
"react-dom": "18.2.0",
28+
"zod": "^3.25.76"
2829
},
2930
"devDependencies": {
3031
"@types/jsonwebtoken": "^9.0.10",

packages/okta/src/Okta.tsx

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,37 @@
11
import React from "react";
2+
import { defineExtension } from "@webiny/project/defineExtension/index.js";
23
import { EnvVar } from "@webiny/project/extensions/index.js";
34
import { Api, Admin } from "@webiny/project-aws";
5+
import { z } from "zod";
46

5-
interface OktaProps {
6-
issuer: string;
7-
clientId: string;
8-
apiConfig: string;
9-
}
10-
11-
export const Okta = (props: OktaProps) => {
12-
return (
13-
<>
14-
{/* Lambda vars */}
15-
<EnvVar varName={"OKTA_ISSUER"} value={props.issuer} />
16-
<EnvVar varName={"OKTA_CLIENT_ID"} value={props.clientId} />
17-
{/* Admin app vars */}
18-
<EnvVar varName={"REACT_APP_IDP_TYPE"} value={"okta"} />
19-
<EnvVar varName={"REACT_APP_OKTA_ISSUER"} value={props.issuer} />
20-
<EnvVar varName={"REACT_APP_OKTA_CLIENT_ID"} value={props.clientId} />
21-
{/* Api extensions */}
22-
<Api.Extension
23-
src={import.meta.dirname + "/api/features/OktaIdp/feature.js"}
24-
exportName={"OktaIdpFeature"}
25-
/>
26-
<Api.Extension src={props.apiConfig} />
27-
{/* Admin extensions */}
28-
<Admin.Extension src={import.meta.dirname + "/admin/Extension.js"} />
29-
</>
30-
);
31-
};
7+
export const Okta = defineExtension({
8+
type: "Project/Okta",
9+
tags: { runtimeContext: "project" },
10+
description: "Enable and configure Okta authentication.",
11+
paramsSchema: z.object({
12+
issuer: z.string().describe("Okta issuer URL."),
13+
clientId: z.string().describe("Okta client ID."),
14+
apiConfig: z.string().describe("Path to API configuration.")
15+
}),
16+
render: props => {
17+
return (
18+
<>
19+
{/* Lambda vars */}
20+
<EnvVar varName={"OKTA_ISSUER"} value={props.issuer} />
21+
<EnvVar varName={"OKTA_CLIENT_ID"} value={props.clientId} />
22+
{/* Admin app vars */}
23+
<EnvVar varName={"REACT_APP_IDP_TYPE"} value={"okta"} />
24+
<EnvVar varName={"REACT_APP_OKTA_ISSUER"} value={props.issuer} />
25+
<EnvVar varName={"REACT_APP_OKTA_CLIENT_ID"} value={props.clientId} />
26+
{/* Api extensions */}
27+
<Api.Extension
28+
src={import.meta.dirname + "/api/features/OktaIdp/feature.js"}
29+
exportName={"OktaIdpFeature"}
30+
/>
31+
<Api.Extension src={props.apiConfig} />
32+
{/* Admin extensions */}
33+
<Admin.Extension src={import.meta.dirname + "/admin/Extension.js"} />
34+
</>
35+
);
36+
}
37+
});
Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,49 @@
11
import React from "react";
2+
import { defineExtension } from "@webiny/project/defineExtension/index.js";
23
import { OpenSearch as PulumiOpenSearch } from "~/pulumi/extensions/index.js";
34
import { Infra } from "~/index.js";
45
import { createPathResolver } from "@webiny/project";
56
import { ProjectDecorator, DatabaseSetup } from "@webiny/project/extensions/index.js";
7+
import { z } from "zod";
68

79
const p = createPathResolver(import.meta.dirname, "OpenSearch");
810

9-
export const OpenSearch = (props: React.ComponentProps<typeof PulumiOpenSearch>) => {
10-
return (
11-
<>
12-
<PulumiOpenSearch {...props} />
13-
{props.enabled && (
14-
<>
15-
{/* Override database setup to indicate OpenSearch is enabled */}
16-
<DatabaseSetup setupName="ddb+os" />
17-
<ProjectDecorator src={p("InjectDdbEsLambdaFnHandler.js")} />
18-
<ProjectDecorator src={p("ReplaceApiLambdaFnHandlers.js")} />
19-
<Infra.Core.BeforeDeploy src={p("EnsureOsServiceRoleBeforeCoreDeploy.js")} />
20-
<Infra.Core.BeforeDeploy src={p("EnsureOsWasDeployed.js")} />
21-
</>
22-
)}
23-
</>
24-
);
25-
};
11+
export const OpenSearch = defineExtension({
12+
type: "Project/OpenSearch",
13+
tags: { runtimeContext: "project" },
14+
description: "Enable and configure Opensearch integration with project-level setup.",
15+
paramsSchema: z.object({
16+
enabled: z.boolean().describe("Whether to enable OpenSearch.").default(false).optional(),
17+
domainName: z.string().describe("The name of the Opensearch domain.").optional(),
18+
indexPrefix: z
19+
.string()
20+
.describe("A prefix to be added to all Opensearch indexes.")
21+
.optional(),
22+
sharedIndexes: z
23+
.boolean()
24+
.describe(
25+
"Whether to use shared indexes across all environments (true) or separate indexes per environment (false)."
26+
)
27+
.default(false)
28+
.optional()
29+
}),
30+
render: props => {
31+
return (
32+
<>
33+
<PulumiOpenSearch {...props} />
34+
{props.enabled && (
35+
<>
36+
{/* Override database setup to indicate OpenSearch is enabled. */}
37+
<DatabaseSetup setupName="ddb+os" />
38+
<ProjectDecorator src={p("InjectDdbEsLambdaFnHandler.js")} />
39+
<ProjectDecorator src={p("ReplaceApiLambdaFnHandlers.js")} />
40+
<Infra.Core.BeforeDeploy
41+
src={p("EnsureOsServiceRoleBeforeCoreDeploy.js")}
42+
/>
43+
<Infra.Core.BeforeDeploy src={p("EnsureOsWasDeployed.js")} />
44+
</>
45+
)}
46+
</>
47+
);
48+
}
49+
});

packages/project/src/defineExtension/createExtensionReactComponent.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ export function createExtensionReactComponent<TParamsSchema extends z.ZodTypeAny
2323
const ExtensionReactComponent: React.FC<
2424
ExtensionReactComponentProps<TParamsSchema>
2525
> = props => {
26+
// If custom render function is provided, use it.
27+
if (extensionParams.render) {
28+
return <>{extensionParams.render(props)}</>;
29+
}
30+
2631
const { name, remove, before, after, ...keyValues } = props;
2732

2833
const getId = useIdGenerator(extensionParams.type);

0 commit comments

Comments
 (0)