diff --git a/apps/admin/src/App.auth0.tsx b/apps/admin/src/App.auth0.tsx
index 94470e11142..15b9bded727 100644
--- a/apps/admin/src/App.auth0.tsx
+++ b/apps/admin/src/App.auth0.tsx
@@ -1,6 +1,7 @@
import React from "react";
import { Admin } from "@webiny/app-serverless-cms";
import { Auth0 } from "@webiny/app-admin-auth0";
+import { Extensions } from "./Extensions";
import "./App.scss";
export const App = () => {
@@ -13,6 +14,7 @@ export const App = () => {
}}
rootAppClientId={String(process.env.REACT_APP_AUTH0_CLIENT_ID)}
/>
+
);
};
diff --git a/apps/admin/src/App.editor.tsx b/apps/admin/src/App.editor.tsx
index d5ad5a4007b..81e29c37ce2 100644
--- a/apps/admin/src/App.editor.tsx
+++ b/apps/admin/src/App.editor.tsx
@@ -1,6 +1,7 @@
import React from "react";
import { Admin } from "@webiny/app-serverless-cms";
import { Cognito } from "@webiny/app-admin-users-cognito";
+import { Extensions } from "./Extensions";
import { Editor } from "@webiny/app-page-builder-editor";
import "./App.scss";
@@ -9,6 +10,7 @@ export const App = () => {
+
);
};
diff --git a/apps/admin/src/App.fm.tsx b/apps/admin/src/App.fm.tsx
index b9b2522a83e..c3a53d9c10e 100644
--- a/apps/admin/src/App.fm.tsx
+++ b/apps/admin/src/App.fm.tsx
@@ -2,6 +2,7 @@ import React, { useCallback } from "react";
import { Admin, createComponentPlugin } from "@webiny/app-serverless-cms";
import { FileManagerFileItem, FileManagerRenderer, OverlayLayout } from "@webiny/app-admin";
import { Cognito } from "@webiny/app-admin-users-cognito";
+import { Extensions } from "./Extensions";
import "./App.scss";
const CustomFileManager = createComponentPlugin(FileManagerRenderer, () => {
@@ -36,6 +37,7 @@ export const App = () => {
+
);
};
diff --git a/apps/admin/src/App.okta.tsx b/apps/admin/src/App.okta.tsx
index 2ec41173259..7ffc0f568f6 100644
--- a/apps/admin/src/App.okta.tsx
+++ b/apps/admin/src/App.okta.tsx
@@ -1,6 +1,7 @@
import React from "react";
import { Admin } from "@webiny/app-serverless-cms";
import { Okta } from "@webiny/app-admin-okta";
+import { Extensions } from "./Extensions";
import "./App.scss";
import { oktaFactory, rootAppClientId } from "./okta";
@@ -9,6 +10,7 @@ export const App = () => {
return (
+
);
};
diff --git a/apps/admin/src/App.tsx b/apps/admin/src/App.tsx
index 2773f643e51..ac6cee40cd1 100644
--- a/apps/admin/src/App.tsx
+++ b/apps/admin/src/App.tsx
@@ -1,12 +1,14 @@
import React from "react";
import { Admin } from "@webiny/app-serverless-cms";
import { Cognito } from "@webiny/app-admin-users-cognito";
+import { Extensions } from "./Extensions";
import "./App.scss";
export const App = () => {
return (
+
);
};
diff --git a/apps/admin/src/Extensions.tsx b/apps/admin/src/Extensions.tsx
new file mode 100644
index 00000000000..00cd662531a
--- /dev/null
+++ b/apps/admin/src/Extensions.tsx
@@ -0,0 +1,6 @@
+// This file is automatically updated via scaffolding utilities.
+import React from "react";
+
+export const Extensions = () => {
+ return <>>;
+};
diff --git a/apps/api/graphql/src/extensions.ts b/apps/api/graphql/src/extensions.ts
new file mode 100644
index 00000000000..658b605320b
--- /dev/null
+++ b/apps/api/graphql/src/extensions.ts
@@ -0,0 +1,4 @@
+// This file is automatically updated via scaffolding utilities.
+export const extensions = () => {
+ return [];
+};
diff --git a/apps/api/graphql/src/index.ts b/apps/api/graphql/src/index.ts
index 5afef095ae9..a957791fc2b 100644
--- a/apps/api/graphql/src/index.ts
+++ b/apps/api/graphql/src/index.ts
@@ -38,13 +38,15 @@ import { createAco } from "@webiny/api-aco";
import { createAcoPageBuilderContext } from "@webiny/api-page-builder-aco";
import { createAuditLogs } from "@webiny/api-audit-logs";
import { createBackgroundTasks } from "@webiny/api-background-tasks-ddb";
-import scaffoldsPlugins from "./plugins/scaffolds";
import { createBenchmarkEnablePlugin } from "~/plugins/benchmarkEnable";
import { createCountDynamoDbTask } from "~/plugins/countDynamoDbTask";
import { createContinuingTask } from "~/plugins/continuingTask";
import { createWebsockets } from "@webiny/api-websockets";
import { createRecordLocking } from "@webiny/api-record-locking";
+import scaffoldsPlugins from "./plugins/scaffolds";
+import { extensions } from "./extensions";
+
const debug = process.env.DEBUG === "true";
const documentClient = getDocumentClient();
@@ -107,7 +109,6 @@ export const handler = createHandler({
createAcoPageBuilderContext(),
createAcoHcmsContext(),
createHcmsTasks(),
- scaffoldsPlugins(),
createFileModelModifier(({ modifier }) => {
modifier.addField({
id: "customField1",
@@ -134,7 +135,11 @@ export const handler = createHandler({
}),
createAuditLogs(),
createCountDynamoDbTask(),
- createContinuingTask()
+ createContinuingTask(),
+
+ // Leave this at the end.
+ scaffoldsPlugins(),
+ extensions()
],
debug
});
diff --git a/apps/theme/global.scss b/extensions/theme/global.scss
similarity index 100%
rename from apps/theme/global.scss
rename to extensions/theme/global.scss
diff --git a/apps/theme/index.ts b/extensions/theme/index.ts
similarity index 100%
rename from apps/theme/index.ts
rename to extensions/theme/index.ts
diff --git a/apps/theme/layouts/forms/DefaultFormLayout.tsx b/extensions/theme/layouts/forms/DefaultFormLayout.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/Cell.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/Cell.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/Cell.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/Cell.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/Field.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/Field.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/Field.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/Field.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/ReCaptchaSection.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/ReCaptchaSection.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/ReCaptchaSection.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/ReCaptchaSection.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/Row.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/Row.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/Row.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/Row.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/SuccessMessage.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/SuccessMessage.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/SuccessMessage.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/SuccessMessage.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/TermsOfServiceSection.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/TermsOfServiceSection.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/TermsOfServiceSection.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/TermsOfServiceSection.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/buttons/Button.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/buttons/Button.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/buttons/Button.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/buttons/Button.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/fields/Checkbox.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/fields/Checkbox.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/fields/Checkbox.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/fields/Checkbox.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/fields/DateTime.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/fields/DateTime.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/fields/DateTime.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/fields/DateTime.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/fields/Hidden.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/fields/Hidden.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/fields/Hidden.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/fields/Hidden.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/fields/Input.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/fields/Input.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/fields/Input.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/fields/Input.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/fields/Radio.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/fields/Radio.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/fields/Radio.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/fields/Radio.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/fields/Select.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/fields/Select.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/fields/Select.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/fields/Select.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/fields/Textarea.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/fields/Textarea.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/fields/Textarea.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/fields/Textarea.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/fields/components/Field.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/Field.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/fields/components/Field.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/fields/components/Field.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldErrorMessage.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldErrorMessage.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldErrorMessage.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldErrorMessage.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldHelperMessage.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldHelperMessage.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldHelperMessage.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldHelperMessage.tsx
diff --git a/apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldLabel.tsx b/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldLabel.tsx
similarity index 100%
rename from apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldLabel.tsx
rename to extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldLabel.tsx
diff --git a/apps/theme/layouts/pages/Static.tsx b/extensions/theme/layouts/pages/Static.tsx
similarity index 100%
rename from apps/theme/layouts/pages/Static.tsx
rename to extensions/theme/layouts/pages/Static.tsx
diff --git a/apps/theme/layouts/pages/Static/Footer.tsx b/extensions/theme/layouts/pages/Static/Footer.tsx
similarity index 100%
rename from apps/theme/layouts/pages/Static/Footer.tsx
rename to extensions/theme/layouts/pages/Static/Footer.tsx
diff --git a/apps/theme/layouts/pages/Static/Header.tsx b/extensions/theme/layouts/pages/Static/Header.tsx
similarity index 100%
rename from apps/theme/layouts/pages/Static/Header.tsx
rename to extensions/theme/layouts/pages/Static/Header.tsx
diff --git a/apps/theme/layouts/pages/Static/HeaderDesktop.tsx b/extensions/theme/layouts/pages/Static/HeaderDesktop.tsx
similarity index 100%
rename from apps/theme/layouts/pages/Static/HeaderDesktop.tsx
rename to extensions/theme/layouts/pages/Static/HeaderDesktop.tsx
diff --git a/apps/theme/layouts/pages/Static/HeaderMobile.tsx b/extensions/theme/layouts/pages/Static/HeaderMobile.tsx
similarity index 100%
rename from apps/theme/layouts/pages/Static/HeaderMobile.tsx
rename to extensions/theme/layouts/pages/Static/HeaderMobile.tsx
diff --git a/apps/theme/layouts/pages/Static/Navigation.tsx b/extensions/theme/layouts/pages/Static/Navigation.tsx
similarity index 100%
rename from apps/theme/layouts/pages/Static/Navigation.tsx
rename to extensions/theme/layouts/pages/Static/Navigation.tsx
diff --git a/apps/theme/layouts/pages/Static/assets/facebook-square-brands.svg b/extensions/theme/layouts/pages/Static/assets/facebook-square-brands.svg
similarity index 100%
rename from apps/theme/layouts/pages/Static/assets/facebook-square-brands.svg
rename to extensions/theme/layouts/pages/Static/assets/facebook-square-brands.svg
diff --git a/apps/theme/layouts/pages/Static/assets/instagram-brands.svg b/extensions/theme/layouts/pages/Static/assets/instagram-brands.svg
similarity index 100%
rename from apps/theme/layouts/pages/Static/assets/instagram-brands.svg
rename to extensions/theme/layouts/pages/Static/assets/instagram-brands.svg
diff --git a/apps/theme/layouts/pages/Static/assets/linkedin-brands.svg b/extensions/theme/layouts/pages/Static/assets/linkedin-brands.svg
similarity index 100%
rename from apps/theme/layouts/pages/Static/assets/linkedin-brands.svg
rename to extensions/theme/layouts/pages/Static/assets/linkedin-brands.svg
diff --git a/apps/theme/layouts/pages/Static/assets/twitter-square-brands.svg b/extensions/theme/layouts/pages/Static/assets/twitter-square-brands.svg
similarity index 100%
rename from apps/theme/layouts/pages/Static/assets/twitter-square-brands.svg
rename to extensions/theme/layouts/pages/Static/assets/twitter-square-brands.svg
diff --git a/apps/theme/package.json b/extensions/theme/package.json
similarity index 100%
rename from apps/theme/package.json
rename to extensions/theme/package.json
diff --git a/apps/theme/theme.ts b/extensions/theme/theme.ts
similarity index 100%
rename from apps/theme/theme.ts
rename to extensions/theme/theme.ts
diff --git a/apps/theme/tsconfig.json b/extensions/theme/tsconfig.json
similarity index 100%
rename from apps/theme/tsconfig.json
rename to extensions/theme/tsconfig.json
diff --git a/package.json b/package.json
index 635cb3b66e8..131a871443f 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,6 @@
"apps/custom",
"apps/website",
"apps/website/prerendering/*",
- "apps/theme",
"apps/core/dynamoToElastic",
"apps/api/apw/*",
"apps/api/fileManager/*",
@@ -18,6 +17,7 @@
"apps/api/pageBuilder/updateSettings",
"apps/api/pageBuilder/import/*",
"apps/api/pageBuilder/export/*",
+ "extensions/theme",
"scripts/buildPackages",
"scripts/prepublishOnly"
]
diff --git a/packages/api-serverless-cms/.babelrc.js b/packages/api-serverless-cms/.babelrc.js
new file mode 100644
index 00000000000..9da7674cb52
--- /dev/null
+++ b/packages/api-serverless-cms/.babelrc.js
@@ -0,0 +1 @@
+module.exports = require("@webiny/project-utils").createBabelConfigForNode({ path: __dirname });
diff --git a/packages/api-serverless-cms/LICENSE b/packages/api-serverless-cms/LICENSE
new file mode 100644
index 00000000000..f772d04d4db
--- /dev/null
+++ b/packages/api-serverless-cms/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) Webiny
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/api-serverless-cms/README.md b/packages/api-serverless-cms/README.md
new file mode 100644
index 00000000000..fc99886f597
--- /dev/null
+++ b/packages/api-serverless-cms/README.md
@@ -0,0 +1,15 @@
+# @webiny/api-serverless-cms
+[![](https://img.shields.io/npm/dw/@webiny/api-serverless-cms.svg)](https://www.npmjs.com/package/@webiny/api-serverless-cms)
+[![](https://img.shields.io/npm/v/@webiny/api-serverless-cms.svg)](https://www.npmjs.com/package/@webiny/api-serverless-cms)
+[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
+[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
+
+## Install
+```
+npm install --save @webiny/api-serverless-cms
+```
+
+Or if you prefer yarn:
+```
+yarn add @webiny/api-serverless-cms
+```
diff --git a/packages/api-serverless-cms/package.json b/packages/api-serverless-cms/package.json
new file mode 100644
index 00000000000..4efd16ef13f
--- /dev/null
+++ b/packages/api-serverless-cms/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "@webiny/api-serverless-cms",
+ "version": "0.0.0",
+ "main": "index.js",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/webiny/webiny-js.git"
+ },
+ "description": "Core package for all of our API packages.",
+ "license": "MIT",
+ "dependencies": {
+ "@webiny/api": "0.0.0",
+ "@webiny/api-aco": "0.0.0",
+ "@webiny/api-file-manager": "0.0.0",
+ "@webiny/api-form-builder": "0.0.0",
+ "@webiny/api-headless-cms": "0.0.0",
+ "@webiny/api-i18n": "0.0.0",
+ "@webiny/api-i18n-content": "0.0.0",
+ "@webiny/api-page-builder": "0.0.0",
+ "@webiny/api-page-builder-aco": "0.0.0",
+ "@webiny/api-prerendering-service": "0.0.0",
+ "@webiny/api-security": "0.0.0",
+ "@webiny/api-tenancy": "0.0.0",
+ "@webiny/handler-client": "0.0.0",
+ "@webiny/handler-graphql": "0.0.0"
+ },
+ "devDependencies": {
+ "@babel/cli": "^7.23.9",
+ "@babel/core": "^7.24.0",
+ "@babel/preset-env": "^7.24.0",
+ "@babel/preset-typescript": "^7.23.3",
+ "@webiny/cli": "0.0.0",
+ "@webiny/project-utils": "0.0.0",
+ "rimraf": "^5.0.5",
+ "ttypescript": "^1.5.13",
+ "typescript": "4.7.4"
+ },
+ "publishConfig": {
+ "access": "public",
+ "directory": "dist"
+ },
+ "scripts": {
+ "build": "yarn webiny run build",
+ "watch": "yarn webiny run watch"
+ },
+ "gitHead": "8476da73b653c89cc1474d968baf55c1b0ae0e5f"
+}
diff --git a/packages/api-serverless-cms/src/index.ts b/packages/api-serverless-cms/src/index.ts
new file mode 100644
index 00000000000..5e87938046f
--- /dev/null
+++ b/packages/api-serverless-cms/src/index.ts
@@ -0,0 +1,43 @@
+import { ClientContext } from "@webiny/handler-client/types";
+import { TenancyContext } from "@webiny/api-tenancy/types";
+import { SecurityContext } from "@webiny/api-security/types";
+import { I18NContext } from "@webiny/api-i18n/types";
+import { I18NContentContext } from "@webiny/api-i18n-content/types";
+import { PbContext } from "@webiny/api-page-builder/graphql/types";
+import { PrerenderingServiceClientContext } from "@webiny/api-prerendering-service/client/types";
+import { FileManagerContext } from "@webiny/api-file-manager/types";
+import { FormBuilderContext } from "@webiny/api-form-builder/types";
+import { CmsContext } from "@webiny/api-headless-cms/types";
+import { AcoContext } from "@webiny/api-aco/types";
+import { PbAcoContext } from "@webiny/api-page-builder-aco/types";
+import { createContextPlugin as baseCreateContextPlugin, ContextPluginCallable } from "@webiny/api";
+import {
+ createGraphQLSchemaPlugin as baseCreateGraphQLSchemaPlugin,
+ GraphQLSchemaPluginConfig
+} from "@webiny/handler-graphql";
+
+export interface Context
+ extends ClientContext,
+ TenancyContext,
+ SecurityContext,
+ I18NContext,
+ I18NContentContext,
+ PbContext,
+ PrerenderingServiceClientContext,
+ FileManagerContext,
+ FormBuilderContext,
+ AcoContext,
+ PbAcoContext,
+ CmsContext {}
+
+export const createContextPlugin = (
+ callable: ContextPluginCallable
+) => {
+ return baseCreateContextPlugin(callable);
+};
+
+export const createGraphQLSchemaPlugin = (
+ config: GraphQLSchemaPluginConfig
+) => {
+ return baseCreateGraphQLSchemaPlugin(config);
+};
diff --git a/packages/api-serverless-cms/tsconfig.build.json b/packages/api-serverless-cms/tsconfig.build.json
new file mode 100644
index 00000000000..1f153853c01
--- /dev/null
+++ b/packages/api-serverless-cms/tsconfig.build.json
@@ -0,0 +1,27 @@
+{
+ "extends": "../../tsconfig.build.json",
+ "include": ["src"],
+ "references": [
+ { "path": "../api/tsconfig.build.json" },
+ { "path": "../api-aco/tsconfig.build.json" },
+ { "path": "../api-file-manager/tsconfig.build.json" },
+ { "path": "../api-form-builder/tsconfig.build.json" },
+ { "path": "../handler-graphql/tsconfig.build.json" },
+ { "path": "../api-headless-cms/tsconfig.build.json" },
+ { "path": "../api-i18n/tsconfig.build.json" },
+ { "path": "../api-i18n-content/tsconfig.build.json" },
+ { "path": "../api-page-builder/tsconfig.build.json" },
+ { "path": "../api-page-builder-aco/tsconfig.build.json" },
+ { "path": "../api-prerendering-service/tsconfig.build.json" },
+ { "path": "../api-security/tsconfig.build.json" },
+ { "path": "../api-tenancy/tsconfig.build.json" },
+ { "path": "../handler-client/tsconfig.build.json" }
+ ],
+ "compilerOptions": {
+ "rootDir": "./src",
+ "outDir": "./dist",
+ "declarationDir": "./dist",
+ "paths": { "~/*": ["./src/*"], "~tests/*": ["./__tests__/*"] },
+ "baseUrl": "."
+ }
+}
diff --git a/packages/api-serverless-cms/tsconfig.json b/packages/api-serverless-cms/tsconfig.json
new file mode 100644
index 00000000000..07dcf392adf
--- /dev/null
+++ b/packages/api-serverless-cms/tsconfig.json
@@ -0,0 +1,58 @@
+{
+ "extends": "../../tsconfig.json",
+ "include": ["src", "__tests__"],
+ "references": [
+ { "path": "../api" },
+ { "path": "../api-aco" },
+ { "path": "../api-file-manager" },
+ { "path": "../api-form-builder" },
+ { "path": "../handler-graphql" },
+ { "path": "../api-headless-cms" },
+ { "path": "../api-i18n" },
+ { "path": "../api-i18n-content" },
+ { "path": "../api-page-builder" },
+ { "path": "../api-page-builder-aco" },
+ { "path": "../api-prerendering-service" },
+ { "path": "../api-security" },
+ { "path": "../api-tenancy" },
+ { "path": "../handler-client" }
+ ],
+ "compilerOptions": {
+ "rootDirs": ["./src", "./__tests__"],
+ "outDir": "./dist",
+ "declarationDir": "./dist",
+ "paths": {
+ "~/*": ["./src/*"],
+ "~tests/*": ["./__tests__/*"],
+ "@webiny/api/*": ["../api/src/*"],
+ "@webiny/api": ["../api/src"],
+ "@webiny/api-aco/*": ["../api-aco/src/*"],
+ "@webiny/api-aco": ["../api-aco/src"],
+ "@webiny/api-file-manager/*": ["../api-file-manager/src/*"],
+ "@webiny/api-file-manager": ["../api-file-manager/src"],
+ "@webiny/api-form-builder/*": ["../api-form-builder/src/*"],
+ "@webiny/api-form-builder": ["../api-form-builder/src"],
+ "@webiny/handler-graphql/*": ["../handler-graphql/src/*"],
+ "@webiny/handler-graphql": ["../handler-graphql/src"],
+ "@webiny/api-headless-cms/*": ["../api-headless-cms/src/*"],
+ "@webiny/api-headless-cms": ["../api-headless-cms/src"],
+ "@webiny/api-i18n/*": ["../api-i18n/src/*"],
+ "@webiny/api-i18n": ["../api-i18n/src"],
+ "@webiny/api-i18n-content/*": ["../api-i18n-content/src/*"],
+ "@webiny/api-i18n-content": ["../api-i18n-content/src"],
+ "@webiny/api-page-builder/*": ["../api-page-builder/src/*"],
+ "@webiny/api-page-builder": ["../api-page-builder/src"],
+ "@webiny/api-page-builder-aco/*": ["../api-page-builder-aco/src/*"],
+ "@webiny/api-page-builder-aco": ["../api-page-builder-aco/src"],
+ "@webiny/api-prerendering-service/*": ["../api-prerendering-service/src/*"],
+ "@webiny/api-prerendering-service": ["../api-prerendering-service/src"],
+ "@webiny/api-security/*": ["../api-security/src/*"],
+ "@webiny/api-security": ["../api-security/src"],
+ "@webiny/api-tenancy/*": ["../api-tenancy/src/*"],
+ "@webiny/api-tenancy": ["../api-tenancy/src"],
+ "@webiny/handler-client/*": ["../handler-client/src/*"],
+ "@webiny/handler-client": ["../handler-client/src"]
+ },
+ "baseUrl": "."
+ }
+}
diff --git a/packages/api-serverless-cms/webiny.config.js b/packages/api-serverless-cms/webiny.config.js
new file mode 100644
index 00000000000..6dff86766c9
--- /dev/null
+++ b/packages/api-serverless-cms/webiny.config.js
@@ -0,0 +1,8 @@
+const { createWatchPackage, createBuildPackage } = require("@webiny/project-utils");
+
+module.exports = {
+ commands: {
+ build: createBuildPackage({ cwd: __dirname }),
+ watch: createWatchPackage({ cwd: __dirname })
+ }
+};
diff --git a/packages/cli-plugin-scaffold-extensions/.babelrc.js b/packages/cli-plugin-scaffold-extensions/.babelrc.js
new file mode 100644
index 00000000000..9da7674cb52
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/.babelrc.js
@@ -0,0 +1 @@
+module.exports = require("@webiny/project-utils").createBabelConfigForNode({ path: __dirname });
diff --git a/packages/cli-plugin-scaffold-extensions/LICENSE b/packages/cli-plugin-scaffold-extensions/LICENSE
new file mode 100644
index 00000000000..f772d04d4db
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) Webiny
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/cli-plugin-scaffold-extensions/README.md b/packages/cli-plugin-scaffold-extensions/README.md
new file mode 100644
index 00000000000..df02f6c9ecd
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/README.md
@@ -0,0 +1,15 @@
+# @webiny/cli-plugin-scaffold-extensions
+[![](https://img.shields.io/npm/dw/@webiny/cli-plugin-scaffold-extensions.svg)](https://www.npmjs.com/package/@webiny/cli-plugin-scaffold-extensions)
+[![](https://img.shields.io/npm/v/@webiny/cli-plugin-scaffold-extensions.svg)](https://www.npmjs.com/package/@webiny/cli-plugin-scaffold-extensions)
+[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
+[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
+
+## Install
+```
+npm install --save @webiny/cli-plugin-scaffold-extensions
+```
+
+Or if you prefer yarn:
+```
+yarn add @webiny/cli-plugin-scaffold-extensions
+```
diff --git a/packages/cli-plugin-scaffold-extensions/package.json b/packages/cli-plugin-scaffold-extensions/package.json
new file mode 100644
index 00000000000..01caf1d8874
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/package.json
@@ -0,0 +1,59 @@
+{
+ "name": "@webiny/cli-plugin-scaffold-extensions",
+ "version": "0.0.0",
+ "description": "Scaffolds essential files for creating a new plugin.",
+ "main": "index.js",
+ "types": "index.d.ts",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/webiny/webiny-js.git",
+ "directory": "packages/cli-plugin-scaffold-extensions"
+ },
+ "author": {
+ "name": "Webiny",
+ "url": "https://www.webiny.com"
+ },
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/webiny/webiny-js/issues"
+ },
+ "homepage": "https://github.com/webiny/webiny-js#readme",
+ "dependencies": {
+ "@webiny/cli": "0.0.0",
+ "@webiny/cli-plugin-scaffold": "0.0.0",
+ "@webiny/error": "0.0.0",
+ "case": "^1.6.3",
+ "execa": "^5.0.0",
+ "load-json-file": "^6.2.0",
+ "ncp": "^2.0.0",
+ "replace-in-path": "^1.1.0",
+ "ts-morph": "^11.0.0",
+ "validate-npm-package-name": "^3.0.0",
+ "write-json-file": "^4.3.0"
+ },
+ "devDependencies": {
+ "@babel/cli": "^7.23.9",
+ "@babel/core": "^7.24.0",
+ "@babel/preset-env": "^7.24.0",
+ "@types/inquirer": "^7.3.1",
+ "@types/ncp": "^2.0.4",
+ "@types/pluralize": "^0.0.29",
+ "@types/validate-npm-package-name": "^3.0.3",
+ "@webiny/project-utils": "0.0.0",
+ "rimraf": "^5.0.5",
+ "typescript": "4.7.4"
+ },
+ "scripts": {
+ "build": "yarn webiny run build",
+ "watch": "yarn webiny run watch"
+ },
+ "publishConfig": {
+ "access": "public",
+ "directory": "dist"
+ },
+ "adio": {
+ "ignoreDirs": [
+ "template"
+ ]
+ }
+}
diff --git a/packages/cli-plugin-scaffold-extensions/src/generators/admin.ts b/packages/cli-plugin-scaffold-extensions/src/generators/admin.ts
new file mode 100644
index 00000000000..940d00c05c5
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/src/generators/admin.ts
@@ -0,0 +1,6 @@
+import { addPluginToReactApp } from "./utils/addPluginToReactApp";
+import { PluginGenerator } from "~/types";
+
+export const adminGenerator: PluginGenerator = async ({ input }) => {
+ await addPluginToReactApp(input);
+};
diff --git a/packages/cli-plugin-scaffold-extensions/src/generators/api.ts b/packages/cli-plugin-scaffold-extensions/src/generators/api.ts
new file mode 100644
index 00000000000..bfd8a55f7cc
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/src/generators/api.ts
@@ -0,0 +1,6 @@
+import { addPluginToApiApp } from "./utils/addPluginToApiApp";
+import { PluginGenerator } from "~/types";
+
+export const apiGenerator: PluginGenerator = async ({ input }) => {
+ await addPluginToApiApp(input);
+};
diff --git a/packages/cli-plugin-scaffold-extensions/src/generators/index.ts b/packages/cli-plugin-scaffold-extensions/src/generators/index.ts
new file mode 100644
index 00000000000..66743d5a83e
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/src/generators/index.ts
@@ -0,0 +1,8 @@
+import { apiGenerator } from "./api";
+import { adminGenerator } from "./admin";
+import { PluginGenerator } from "~/types";
+
+export const generators: Record = {
+ api: apiGenerator,
+ admin: adminGenerator
+};
diff --git a/packages/cli-plugin-scaffold-extensions/src/generators/utils/addPluginToApiApp.tsx b/packages/cli-plugin-scaffold-extensions/src/generators/utils/addPluginToApiApp.tsx
new file mode 100644
index 00000000000..bbcaa75b252
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/src/generators/utils/addPluginToApiApp.tsx
@@ -0,0 +1,53 @@
+import { Project, ArrayLiteralExpression, Node } from "ts-morph";
+import path from "path";
+import { formatCode } from "@webiny/cli-plugin-scaffold/utils";
+
+interface Params {
+ name: string;
+ packageName: string;
+}
+
+export const addPluginToApiApp = async (params: Params): Promise => {
+ const { name, packageName } = params;
+
+ const extensionsFilePath = path.join("apps", "api", "graphql", "src", "extensions.ts");
+
+ const extensionFactory = name + "ExtensionFactory";
+ const importName = "{ createExtension as " + extensionFactory + " }";
+ const importPath = packageName;
+
+ const project = new Project();
+ project.addSourceFileAtPath(extensionsFilePath);
+
+ const source = project.getSourceFileOrThrow(extensionsFilePath);
+
+ const existingImportDeclaration = source.getImportDeclaration(importPath);
+ if (existingImportDeclaration) {
+ throw new Error(
+ `Could not import "${importPath}" in "${extensionsFilePath}" as it already exists.`
+ );
+ }
+
+ let index = 1;
+
+ const importDeclarations = source.getImportDeclarations();
+ if (importDeclarations.length) {
+ const last = importDeclarations[importDeclarations.length - 1];
+ index = last.getChildIndex() + 1;
+ }
+
+ source.insertImportDeclaration(index, {
+ defaultImport: importName,
+ moduleSpecifier: importPath
+ });
+
+ const pluginsArray = source.getFirstDescendant(node =>
+ Node.isArrayLiteralExpression(node)
+ ) as ArrayLiteralExpression;
+
+ pluginsArray.addElement(`${extensionFactory}()`);
+
+ await source.save();
+
+ await formatCode(extensionsFilePath, {});
+};
diff --git a/packages/cli-plugin-scaffold-extensions/src/generators/utils/addPluginToReactApp.tsx b/packages/cli-plugin-scaffold-extensions/src/generators/utils/addPluginToReactApp.tsx
new file mode 100644
index 00000000000..06c4891456d
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/src/generators/utils/addPluginToReactApp.tsx
@@ -0,0 +1,84 @@
+import { Project, Node, JsxFragment } from "ts-morph";
+import path from "path";
+import { formatCode } from "@webiny/cli-plugin-scaffold/utils";
+
+interface Params {
+ name: string;
+ packageName: string;
+}
+
+export const addPluginToReactApp = async (params: Params): Promise => {
+ const { name, packageName } = params;
+
+ const extensionsFilePath = path.join("apps", "admin", "src", "Extensions.tsx");
+
+ const extensionFactory = name + "ExtensionFactory";
+ const importName = "{ createExtension as " + extensionFactory + " }";
+ const importPath = packageName;
+
+ const project = new Project();
+ project.addSourceFileAtPath(extensionsFilePath);
+
+ const source = project.getSourceFileOrThrow(extensionsFilePath);
+
+ const existingImportDeclaration = source.getImportDeclaration(importPath);
+ if (existingImportDeclaration) {
+ throw new Error(
+ `Could not import "${importPath}" in "${extensionsFilePath}" as it already exists.`
+ );
+ }
+
+ let index = 1;
+
+ const importDeclarations = source.getImportDeclarations();
+ if (importDeclarations.length) {
+ const last = importDeclarations[importDeclarations.length - 1];
+ index = last.getChildIndex() + 1;
+ }
+
+ source.insertImportDeclaration(index, {
+ defaultImport: importName,
+ moduleSpecifier: importPath
+ });
+
+ const extensionsIdentifier = source.getFirstDescendant(node => {
+ if (!Node.isIdentifier(node)) {
+ return false;
+ }
+
+ return node.getText() === "Extensions";
+ });
+
+ if (!extensionsIdentifier) {
+ throw new Error(
+ `Could not find the "Extensions" React component in "${extensionsFilePath}". Did you maybe change the name of the component?`
+ );
+ }
+
+ const extensionsArrowFn = extensionsIdentifier.getNextSibling(node =>
+ Node.isArrowFunction(node)
+ );
+ if (!extensionsArrowFn) {
+ throw new Error(
+ `Could not find the "Extensions" React component in "${extensionsFilePath}". Did you maybe change its definition? It should be an arrow function.`
+ );
+ }
+
+ const extensionsArrowFnFragment = extensionsArrowFn.getFirstDescendant(node => {
+ return Node.isJsxFragment(node);
+ }) as JsxFragment;
+
+ const extensionsArrowFnFragmentChildrenText = extensionsArrowFnFragment
+ .getFullText()
+ .replace("<>", "")
+ .replace(">", "")
+ .trim();
+
+ extensionsArrowFnFragment.replaceWithText(
+ `<>{${name}ExtensionFactory()}${extensionsArrowFnFragmentChildrenText}>`
+ );
+
+ await source.save();
+
+ await formatCode(extensionsFilePath, {});
+};
diff --git a/packages/cli-plugin-scaffold-extensions/src/index.ts b/packages/cli-plugin-scaffold-extensions/src/index.ts
new file mode 100644
index 00000000000..eb812b22fce
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/src/index.ts
@@ -0,0 +1,184 @@
+import { CliCommandScaffoldTemplate, PackageJson } from "@webiny/cli-plugin-scaffold/types";
+import fs from "fs";
+import path from "path";
+import util from "util";
+import ncpBase from "ncp";
+import readJson from "load-json-file";
+import writeJson from "write-json-file";
+import execa from "execa";
+import Case from "case";
+import { replaceInPath } from "replace-in-path";
+import WebinyError from "@webiny/error";
+import validateNpmPackageName from "validate-npm-package-name";
+/**
+ * TODO: rewrite cli into typescript
+ */
+// @ts-expect-error
+import { getProject, log } from "@webiny/cli/utils";
+import { generators } from "./generators";
+
+const ncp = util.promisify(ncpBase.ncp);
+
+interface Input {
+ type: string;
+ name: string;
+ packageName: string;
+ location: string;
+}
+
+const EXTENSIONS_ROOT_FOLDER = "extensions";
+
+export default (): CliCommandScaffoldTemplate => ({
+ name: "cli-plugin-scaffold-template-extensions",
+ type: "cli-plugin-scaffold-template",
+ templateName: "new-extension",
+ scaffold: {
+ name: "New Extension",
+ description: "Scaffolds essential files for creating a new extension.",
+ questions: () => {
+ return [
+ {
+ name: "type",
+ message: "What type of an extension do you want to create?",
+ type: "list",
+ choices: [
+ { name: "Admin extension", value: "admin" },
+ { name: "API extension", value: "api" }
+ ]
+ },
+ {
+ name: "name",
+ message: "Enter the extension name:",
+ default: "myCustomExtension",
+ validate: name => {
+ if (!name) {
+ return "Missing extension name.";
+ }
+
+ const isValidName = name === Case.camel(name);
+ if (!isValidName) {
+ return `Please use camel case when providing the name of the extension (for example "myCustomExtension").`;
+ }
+
+ return true;
+ }
+ },
+ {
+ name: "packageName",
+ message: "Enter the package name:",
+ default: (answers: Input) => {
+ return Case.kebab(answers.name);
+ },
+ validate: pkgName => {
+ if (!pkgName) {
+ return "Missing package name.";
+ }
+
+ const isValidName = validateNpmPackageName(pkgName);
+ if (!isValidName) {
+ return `Package name must look something like "my-custom-extension".`;
+ }
+
+ return true;
+ }
+ },
+ {
+ name: "location",
+ message: `Enter the extension location:`,
+ default: (answers: Input) => {
+ return `${EXTENSIONS_ROOT_FOLDER}/${answers.name}`;
+ },
+ validate: location => {
+ if (!location) {
+ return "Please enter the package location.";
+ }
+
+ if (!location.startsWith(`${EXTENSIONS_ROOT_FOLDER}/`)) {
+ return `Package location must start with "${EXTENSIONS_ROOT_FOLDER}/".`;
+ }
+
+ const locationPath = path.resolve(location);
+ if (fs.existsSync(locationPath)) {
+ return `The target location already exists "${location}".`;
+ }
+
+ return true;
+ }
+ }
+ ];
+ },
+ generate: async ({ input, ora }) => {
+ const { type, name } = input;
+ if (!type) {
+ throw new Error("Missing extension type.");
+ }
+
+ const templatePath = path.join(__dirname, "templates", type);
+ const templateExists = fs.existsSync(templatePath);
+ if (!templateExists) {
+ throw new Error("Unknown extension type.");
+ }
+
+ if (!name) {
+ throw new Error("Missing extension name.");
+ }
+
+ let { packageName, location } = input;
+ if (!packageName) {
+ packageName = Case.kebab(name);
+ }
+
+ if (!location) {
+ location = `${EXTENSIONS_ROOT_FOLDER}/${name}`;
+ }
+
+ if (fs.existsSync(location)) {
+ throw new WebinyError(`The target location already exists "${location}"`);
+ }
+
+ try {
+ ora.start(`Creating ${log.success.hl(name)} extension...`);
+
+ // Copy template files
+ fs.mkdirSync(location, { recursive: true });
+ await ncp(templatePath, location);
+
+ const project = getProject();
+
+ const baseTsConfigFullPath = path.resolve(project.root, "tsconfig.json");
+ const baseTsConfigRelativePath = path.relative(location, baseTsConfigFullPath);
+
+ const codeReplacements = [
+ { find: "PACKAGE_NAME", replaceWith: packageName },
+ {
+ find: "BASE_TSCONFIG_PATH",
+ replaceWith: baseTsConfigRelativePath
+ }
+ ];
+
+ replaceInPath(path.join(location, "**/*.*"), codeReplacements);
+
+ // Add package to workspaces
+ const rootPackageJsonPath = path.join(project.root, "package.json");
+ const rootPackageJson = await readJson(rootPackageJsonPath);
+ if (!rootPackageJson.workspaces.packages.includes(location)) {
+ rootPackageJson.workspaces.packages.push(location);
+ await writeJson(rootPackageJsonPath, rootPackageJson);
+ }
+
+ if (typeof generators[type] === "function") {
+ await generators[type]({ input: { name, packageName } });
+ }
+
+ // Once everything is done, run `yarn` so the new packages are automatically installed.
+ await execa("yarn");
+
+ ora.succeed(`New extension created in ${log.success.hl(location)}.`);
+ } catch (err) {
+ ora.fail("Could not create extension. Please check the logs below.");
+ console.log();
+ console.log(err);
+ }
+ }
+ }
+});
diff --git a/packages/cli-plugin-scaffold-extensions/src/types.ts b/packages/cli-plugin-scaffold-extensions/src/types.ts
new file mode 100644
index 00000000000..034301c7096
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/src/types.ts
@@ -0,0 +1,8 @@
+interface PluginGeneratorParams {
+ input: {
+ name: string;
+ packageName: string;
+ };
+}
+
+export type PluginGenerator = (params: PluginGeneratorParams) => Promise;
diff --git a/packages/cli-plugin-scaffold-extensions/templates/admin/package.json b/packages/cli-plugin-scaffold-extensions/templates/admin/package.json
new file mode 100644
index 00000000000..6b600cd715b
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/templates/admin/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "PACKAGE_NAME",
+ "main": "src/index.tsx",
+ "version": "1.0.0"
+}
diff --git a/packages/cli-plugin-scaffold-extensions/templates/admin/src/index.tsx b/packages/cli-plugin-scaffold-extensions/templates/admin/src/index.tsx
new file mode 100644
index 00000000000..9aca87d931c
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/templates/admin/src/index.tsx
@@ -0,0 +1,5 @@
+import React from "react";
+
+export const createExtension = () => {
+ return <>{/* Your code here. */}>;
+};
diff --git a/packages/cli-plugin-scaffold-extensions/templates/admin/tsconfig.json b/packages/cli-plugin-scaffold-extensions/templates/admin/tsconfig.json
new file mode 100644
index 00000000000..31464829d4e
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/templates/admin/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "extends": "BASE_TSCONFIG_PATH",
+ "include": ["src"]
+}
diff --git a/packages/cli-plugin-scaffold-extensions/templates/api/package.json b/packages/cli-plugin-scaffold-extensions/templates/api/package.json
new file mode 100644
index 00000000000..4261ad1dad7
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/templates/api/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "PACKAGE_NAME",
+ "main": "src/index.ts",
+ "version": "1.0.0"
+}
diff --git a/packages/cli-plugin-scaffold-extensions/templates/api/src/index.ts b/packages/cli-plugin-scaffold-extensions/templates/api/src/index.ts
new file mode 100644
index 00000000000..34b9cd491b3
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/templates/api/src/index.ts
@@ -0,0 +1,5 @@
+export const createExtension = () => {
+ return [
+ // Your code here.
+ ];
+};
diff --git a/packages/cli-plugin-scaffold-extensions/templates/api/tsconfig.json b/packages/cli-plugin-scaffold-extensions/templates/api/tsconfig.json
new file mode 100644
index 00000000000..31464829d4e
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/templates/api/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "extends": "BASE_TSCONFIG_PATH",
+ "include": ["src"]
+}
diff --git a/packages/cli-plugin-scaffold-extensions/tsconfig.build.json b/packages/cli-plugin-scaffold-extensions/tsconfig.build.json
new file mode 100644
index 00000000000..b4b3446f615
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/tsconfig.build.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../../tsconfig.build.json",
+ "include": ["src"],
+ "references": [
+ { "path": "../cli-plugin-scaffold/tsconfig.build.json" },
+ { "path": "../error/tsconfig.build.json" }
+ ],
+ "compilerOptions": {
+ "rootDir": "./src",
+ "outDir": "./dist",
+ "declarationDir": "./dist",
+ "paths": { "~/*": ["./src/*"], "~tests/*": ["./__tests__/*"] },
+ "baseUrl": "."
+ }
+}
diff --git a/packages/cli-plugin-scaffold-extensions/tsconfig.json b/packages/cli-plugin-scaffold-extensions/tsconfig.json
new file mode 100644
index 00000000000..442dd9125b9
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "extends": "../../tsconfig.json",
+ "include": ["src", "__tests__"],
+ "references": [{ "path": "../cli-plugin-scaffold" }, { "path": "../error" }],
+ "compilerOptions": {
+ "rootDirs": ["./src", "./__tests__"],
+ "outDir": "./dist",
+ "declarationDir": "./dist",
+ "paths": {
+ "~/*": ["./src/*"],
+ "~tests/*": ["./__tests__/*"],
+ "@webiny/cli-plugin-scaffold/*": ["../cli-plugin-scaffold/src/*"],
+ "@webiny/cli-plugin-scaffold": ["../cli-plugin-scaffold/src"],
+ "@webiny/error/*": ["../error/src/*"],
+ "@webiny/error": ["../error/src"]
+ },
+ "baseUrl": "."
+ }
+}
diff --git a/packages/cli-plugin-scaffold-extensions/webiny.config.js b/packages/cli-plugin-scaffold-extensions/webiny.config.js
new file mode 100644
index 00000000000..240ce95d511
--- /dev/null
+++ b/packages/cli-plugin-scaffold-extensions/webiny.config.js
@@ -0,0 +1,18 @@
+const util = require("util");
+const path = require("path");
+const ncpBase = require("ncp");
+const ncp = util.promisify(ncpBase.ncp);
+
+const { createWatchPackage, createBuildPackage } = require("@webiny/project-utils");
+
+module.exports = {
+ commands: {
+ build: async (options, context) => {
+ await createBuildPackage({ cwd: __dirname })(options, context);
+ const from = path.join(__dirname, "templates");
+ const to = path.join(__dirname, "dist/templates");
+ await ncp(from, to);
+ },
+ watch: createWatchPackage({ cwd: __dirname })
+ }
+};
diff --git a/packages/cli-plugin-scaffold/src/index.ts b/packages/cli-plugin-scaffold/src/index.ts
index 13a727e3a37..011b2c4a9b7 100644
--- a/packages/cli-plugin-scaffold/src/index.ts
+++ b/packages/cli-plugin-scaffold/src/index.ts
@@ -5,8 +5,20 @@ export default (): CliCommandPlugin => ({
type: "cli-command",
name: "cli-command-scaffold",
create({ yargs, context }) {
- yargs.command("scaffold", "Generate boilerplate code", () => {
- return scaffold({ context });
- });
+ yargs.command(
+ "scaffold [template-name]",
+ "Generate boilerplate code",
+ (yargs: Record) => {
+ yargs.example("$0 scaffold");
+ yargs.example("$0 scaffold new-extension --type admin --name customFilePreview");
+ yargs.positional("templateName", {
+ describe: `Name of the scaffold to run (useful when running in non-interactive mode).`,
+ type: "string"
+ });
+ },
+ (argv: Record) => {
+ return scaffold(context, argv);
+ }
+ );
}
});
diff --git a/packages/cli-plugin-scaffold/src/scaffold.ts b/packages/cli-plugin-scaffold/src/scaffold.ts
index c04a8e9a1ca..615547cdd24 100644
--- a/packages/cli-plugin-scaffold/src/scaffold.ts
+++ b/packages/cli-plugin-scaffold/src/scaffold.ts
@@ -1,7 +1,7 @@
import ora from "ora";
import inquirer from "inquirer";
import chalk from "chalk";
-import { CliCommandScaffoldTemplate } from "./types";
+import { CliCommandScaffold, CliCommandScaffoldTemplate } from "./types";
import { CliContext } from "@webiny/cli/types";
const wait = (ms?: number): Promise => {
@@ -10,13 +10,7 @@ const wait = (ms?: number): Promise => {
});
};
-interface ScaffoldArgs {
- context: CliContext;
-}
-
-export const scaffold = async (args: ScaffoldArgs) => {
- const { context } = args;
-
+export const scaffold = async (context: CliContext, args: Record) => {
const scaffoldPlugins = context.plugins.byType(
"cli-plugin-scaffold-template"
);
@@ -27,50 +21,65 @@ export const scaffold = async (args: ScaffoldArgs) => {
process.exit(1);
}
- const choices = scaffoldPlugins.map(plugin => {
- const { name, description } = plugin.scaffold;
+ let scaffold: CliCommandScaffold>;
+ let input: any;
- return {
- name: `${chalk.bold(name)}\n ${description}\n`,
- short: name,
- value: plugin.name
- };
- });
+ if (args.templateName) {
+ const scaffoldPlugin = scaffoldPlugins.find(p => p.templateName === args.templateName);
+ if (!scaffoldPlugin) {
+ console.log(`🚨 We couldn't find the scaffold with the "${args.templateName}" alias.`);
+ process.exit(1);
+ }
- const { selectedPluginName } = await inquirer.prompt({
- type: "list",
- pageSize: 18,
- name: "selectedPluginName",
- message: "Choose a scaffold:",
- choices
- });
+ scaffold = scaffoldPlugin!.scaffold;
+ input = args;
+ } else {
+ const choices = scaffoldPlugins.map(plugin => {
+ const { name, description } = plugin.scaffold;
- const { scaffold } = context.plugins.byName(selectedPluginName);
+ return {
+ name: `${chalk.bold(name)}\n ${description}\n`,
+ short: name,
+ value: plugin.name
+ };
+ });
- const questions =
- typeof scaffold.questions === "function"
- ? scaffold.questions({ context })
- : scaffold.questions;
+ const { selectedPluginName } = await inquirer.prompt({
+ type: "list",
+ pageSize: 18,
+ name: "selectedPluginName",
+ message: "Choose a scaffold:",
+ choices
+ });
+
+ ({ scaffold } = context.plugins.byName(selectedPluginName));
+
+ const questions =
+ typeof scaffold.questions === "function"
+ ? scaffold.questions({ context })
+ : scaffold.questions;
+
+ input = await inquirer.prompt(questions);
+ }
- const input = await inquirer.prompt(questions);
const oraInstance = ora();
const callbackArgs = { input, context, wait, ora: oraInstance, inquirer };
try {
- if (typeof scaffold.onGenerate === "function") {
- await scaffold.onGenerate(callbackArgs);
+ if (typeof scaffold!.onGenerate === "function") {
+ await scaffold!.onGenerate(callbackArgs);
}
- await scaffold.generate(callbackArgs);
+ await scaffold!.generate(callbackArgs);
- if (typeof scaffold.onSuccess === "function") {
- await scaffold.onSuccess(callbackArgs);
+ if (typeof scaffold!.onSuccess === "function") {
+ await scaffold!.onSuccess(callbackArgs);
}
} catch (e) {
oraInstance.stop();
- if (typeof scaffold.onError === "function") {
- await scaffold.onError({ ...callbackArgs, error: e });
+ if (typeof scaffold!.onError === "function") {
+ await scaffold!.onError({ ...callbackArgs, error: e });
} else {
console.log(e);
}
diff --git a/packages/cli-plugin-scaffold/src/types.ts b/packages/cli-plugin-scaffold/src/types.ts
index 4f279d8bc24..f4771101c97 100644
--- a/packages/cli-plugin-scaffold/src/types.ts
+++ b/packages/cli-plugin-scaffold/src/types.ts
@@ -79,7 +79,7 @@ export interface CliCommandScaffoldCallableWithErrorArgs> {
+export interface CliCommandScaffold> {
/**
* Name of the scaffold to be picked from list of choices.
*/
@@ -123,6 +123,13 @@ export interface CliCommandScaffoldTemplate = Reco
* A type of the plugin.
*/
type: "cli-plugin-scaffold-template";
+
+ /**
+ * Template name. Can be used when running the scaffold command in
+ * non-interactive mode (for example: `webiny scaffold new-template`).
+ */
+ templateName?: string;
+
/**
* The scaffold definition.
*/
diff --git a/packages/cli-plugin-scaffold/src/utils/updateScaffoldsIndexFile.ts b/packages/cli-plugin-scaffold/src/utils/updateScaffoldsIndexFile.ts
index be0e4994e1f..9d6fe544bf6 100644
--- a/packages/cli-plugin-scaffold/src/utils/updateScaffoldsIndexFile.ts
+++ b/packages/cli-plugin-scaffold/src/utils/updateScaffoldsIndexFile.ts
@@ -4,9 +4,10 @@ interface Params {
scaffoldsIndexPath: string;
importName: string;
importPath: string;
+ pluginsArrayElement?: string;
}
export default async (params: Params): Promise => {
- const { scaffoldsIndexPath, importName, importPath } = params;
+ const { scaffoldsIndexPath, importName, importPath, pluginsArrayElement } = params;
const project = new Project();
project.addSourceFileAtPath(scaffoldsIndexPath);
@@ -34,7 +35,7 @@ export default async (params: Params): Promise => {
Node.isArrayLiteralExpression(node)
) as ArrayLiteralExpression;
- pluginsArray.addElement(importName);
+ pluginsArray.addElement(pluginsArrayElement || importName);
await source.save();
};
diff --git a/packages/cwp-template-aws/template/common/apps/admin/src/App.tsx b/packages/cwp-template-aws/template/common/apps/admin/src/App.tsx
index 2773f643e51..6526bd7faa8 100644
--- a/packages/cwp-template-aws/template/common/apps/admin/src/App.tsx
+++ b/packages/cwp-template-aws/template/common/apps/admin/src/App.tsx
@@ -1,12 +1,15 @@
import React from "react";
import { Admin } from "@webiny/app-serverless-cms";
import { Cognito } from "@webiny/app-admin-users-cognito";
+import { Extensions } from "./Extensions";
+
import "./App.scss";
export const App = () => {
return (
+
);
};
diff --git a/packages/cwp-template-aws/template/common/apps/admin/src/Extensions.tsx b/packages/cwp-template-aws/template/common/apps/admin/src/Extensions.tsx
new file mode 100644
index 00000000000..00cd662531a
--- /dev/null
+++ b/packages/cwp-template-aws/template/common/apps/admin/src/Extensions.tsx
@@ -0,0 +1,6 @@
+// This file is automatically updated via scaffolding utilities.
+import React from "react";
+
+export const Extensions = () => {
+ return <>>;
+};
diff --git a/packages/cwp-template-aws/template/common/apps/theme/global.scss b/packages/cwp-template-aws/template/common/extensions/theme/global.scss
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/global.scss
rename to packages/cwp-template-aws/template/common/extensions/theme/global.scss
diff --git a/packages/cwp-template-aws/template/common/apps/theme/index.ts b/packages/cwp-template-aws/template/common/extensions/theme/index.ts
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/index.ts
rename to packages/cwp-template-aws/template/common/extensions/theme/index.ts
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/Cell.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/Cell.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/Cell.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/Cell.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/Field.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/Field.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/Field.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/Field.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/ReCaptchaSection.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/ReCaptchaSection.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/ReCaptchaSection.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/ReCaptchaSection.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/Row.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/Row.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/Row.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/Row.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/SuccessMessage.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/SuccessMessage.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/SuccessMessage.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/SuccessMessage.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/TermsOfServiceSection.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/TermsOfServiceSection.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/TermsOfServiceSection.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/TermsOfServiceSection.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/buttons/Button.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/buttons/Button.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/buttons/Button.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/buttons/Button.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Checkbox.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Checkbox.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Checkbox.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Checkbox.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/DateTime.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/DateTime.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/DateTime.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/DateTime.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Hidden.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Hidden.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Hidden.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Hidden.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Input.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Input.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Input.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Input.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Radio.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Radio.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Radio.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Radio.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Select.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Select.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Select.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Select.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Textarea.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Textarea.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/Textarea.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/Textarea.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/components/Field.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/Field.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/components/Field.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/Field.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldErrorMessage.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldErrorMessage.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldErrorMessage.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldErrorMessage.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldHelperMessage.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldHelperMessage.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldHelperMessage.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldHelperMessage.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldLabel.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldLabel.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/forms/DefaultFormLayout/fields/components/FieldLabel.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/forms/DefaultFormLayout/fields/components/FieldLabel.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/Footer.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/Footer.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/Footer.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/Footer.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/Header.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/Header.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/Header.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/Header.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/HeaderDesktop.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/HeaderDesktop.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/HeaderDesktop.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/HeaderDesktop.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/HeaderMobile.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/HeaderMobile.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/HeaderMobile.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/HeaderMobile.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/Navigation.tsx b/packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/Navigation.tsx
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/Navigation.tsx
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/Navigation.tsx
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/assets/facebook-square-brands.svg b/packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/assets/facebook-square-brands.svg
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/assets/facebook-square-brands.svg
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/assets/facebook-square-brands.svg
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/assets/instagram-brands.svg b/packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/assets/instagram-brands.svg
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/assets/instagram-brands.svg
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/assets/instagram-brands.svg
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/assets/linkedin-brands.svg b/packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/assets/linkedin-brands.svg
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/assets/linkedin-brands.svg
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/assets/linkedin-brands.svg
diff --git a/packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/assets/twitter-square-brands.svg b/packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/assets/twitter-square-brands.svg
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/layouts/pages/Static/assets/twitter-square-brands.svg
rename to packages/cwp-template-aws/template/common/extensions/theme/layouts/pages/Static/assets/twitter-square-brands.svg
diff --git a/packages/cwp-template-aws/template/common/apps/theme/package.json b/packages/cwp-template-aws/template/common/extensions/theme/package.json
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/package.json
rename to packages/cwp-template-aws/template/common/extensions/theme/package.json
diff --git a/packages/cwp-template-aws/template/common/apps/theme/theme.ts b/packages/cwp-template-aws/template/common/extensions/theme/theme.ts
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/theme.ts
rename to packages/cwp-template-aws/template/common/extensions/theme/theme.ts
diff --git a/packages/cwp-template-aws/template/common/apps/theme/tsconfig.json b/packages/cwp-template-aws/template/common/extensions/theme/tsconfig.json
similarity index 100%
rename from packages/cwp-template-aws/template/common/apps/theme/tsconfig.json
rename to packages/cwp-template-aws/template/common/extensions/theme/tsconfig.json
diff --git a/packages/cwp-template-aws/template/common/webiny.project.ts b/packages/cwp-template-aws/template/common/webiny.project.ts
index 8de03c7a9f9..0e37a5ca086 100644
--- a/packages/cwp-template-aws/template/common/webiny.project.ts
+++ b/packages/cwp-template-aws/template/common/webiny.project.ts
@@ -6,6 +6,7 @@ import cliAwsTemplate from "@webiny/cwp-template-aws/cli";
import cliScaffold from "@webiny/cli-plugin-scaffold";
import cliScaffoldExtendGraphQlApi from "@webiny/cli-plugin-scaffold-graphql-service";
import cliScaffoldAdminModule from "@webiny/cli-plugin-scaffold-admin-app-module";
+import cliScaffoldExtensions from "@webiny/cli-plugin-scaffold-extensions";
import cliScaffoldCiCd from "@webiny/cli-plugin-scaffold-ci";
export default {
@@ -21,6 +22,7 @@ export default {
cliScaffold(),
cliScaffoldExtendGraphQlApi(),
cliScaffoldAdminModule(),
+ cliScaffoldExtensions(),
cliScaffoldCiCd()
]
},
diff --git a/packages/cwp-template-aws/template/ddb-es/apps/api/graphql/src/extensions.ts b/packages/cwp-template-aws/template/ddb-es/apps/api/graphql/src/extensions.ts
new file mode 100644
index 00000000000..658b605320b
--- /dev/null
+++ b/packages/cwp-template-aws/template/ddb-es/apps/api/graphql/src/extensions.ts
@@ -0,0 +1,4 @@
+// This file is automatically updated via scaffolding utilities.
+export const extensions = () => {
+ return [];
+};
diff --git a/packages/cwp-template-aws/template/ddb-es/apps/api/graphql/src/index.ts b/packages/cwp-template-aws/template/ddb-es/apps/api/graphql/src/index.ts
index 690bc8e2b1a..2056a49a986 100644
--- a/packages/cwp-template-aws/template/ddb-es/apps/api/graphql/src/index.ts
+++ b/packages/cwp-template-aws/template/ddb-es/apps/api/graphql/src/index.ts
@@ -43,6 +43,7 @@ import { createRecordLocking } from "@webiny/api-record-locking";
// Imports plugins created via scaffolding utilities.
import scaffoldsPlugins from "./plugins/scaffolds";
+import { extensions } from "./extensions";
const debug = process.env.DEBUG === "true";
@@ -118,7 +119,8 @@ export const handler = createHandler({
createAcoHcmsContext(),
createHcmsTasks(),
createAuditLogs(),
- scaffoldsPlugins()
+ scaffoldsPlugins(),
+ extensions()
],
debug
});
diff --git a/packages/cwp-template-aws/template/ddb-es/dependencies.json b/packages/cwp-template-aws/template/ddb-es/dependencies.json
index f7289c22c0f..26550e55dde 100644
--- a/packages/cwp-template-aws/template/ddb-es/dependencies.json
+++ b/packages/cwp-template-aws/template/ddb-es/dependencies.json
@@ -8,6 +8,7 @@
"@webiny/cli-plugin-scaffold-admin-app-module": "latest",
"@webiny/cli-plugin-scaffold-graphql-service": "latest",
"@webiny/cli-plugin-scaffold-ci": "latest",
+ "@webiny/cli-plugin-scaffold-extensions": "latest",
"@webiny/cli-plugin-workspaces": "latest",
"@webiny/cli-plugin-deploy-pulumi": "latest",
"@webiny/project-utils": "latest",
@@ -49,14 +50,7 @@
"typescript": "4.7.4"
},
"workspaces": {
- "packages": [
- "apps/admin",
- "apps/website",
- "apps/theme",
- "apps/api/graphql",
- "apps/api/headlessCMS",
- "packages/*"
- ]
+ "packages": ["apps/admin", "apps/website", "apps/api/graphql", "extensions/theme", "packages/*"]
},
"scripts": {
"test": "jest --config jest.config.js --passWithNoTests",
diff --git a/packages/cwp-template-aws/template/ddb-os/apps/api/graphql/src/extensions.ts b/packages/cwp-template-aws/template/ddb-os/apps/api/graphql/src/extensions.ts
new file mode 100644
index 00000000000..658b605320b
--- /dev/null
+++ b/packages/cwp-template-aws/template/ddb-os/apps/api/graphql/src/extensions.ts
@@ -0,0 +1,4 @@
+// This file is automatically updated via scaffolding utilities.
+export const extensions = () => {
+ return [];
+};
diff --git a/packages/cwp-template-aws/template/ddb-os/apps/api/graphql/src/index.ts b/packages/cwp-template-aws/template/ddb-os/apps/api/graphql/src/index.ts
index 1ae3afb7698..d1199759a1e 100644
--- a/packages/cwp-template-aws/template/ddb-os/apps/api/graphql/src/index.ts
+++ b/packages/cwp-template-aws/template/ddb-os/apps/api/graphql/src/index.ts
@@ -43,6 +43,7 @@ import { createRecordLocking } from "@webiny/api-record-locking";
// Imports plugins created via scaffolding utilities.
import scaffoldsPlugins from "./plugins/scaffolds";
+import { extensions } from "./extensions";
const debug = process.env.DEBUG === "true";
@@ -118,7 +119,8 @@ export const handler = createHandler({
createAcoHcmsContext(),
createHcmsTasks(),
createAuditLogs(),
- scaffoldsPlugins()
+ scaffoldsPlugins(),
+ extensions()
],
debug
});
diff --git a/packages/cwp-template-aws/template/ddb-os/dependencies.json b/packages/cwp-template-aws/template/ddb-os/dependencies.json
index a3cfe9f2045..667ed0a2aa9 100644
--- a/packages/cwp-template-aws/template/ddb-os/dependencies.json
+++ b/packages/cwp-template-aws/template/ddb-os/dependencies.json
@@ -8,6 +8,7 @@
"@webiny/cli-plugin-scaffold-admin-app-module": "latest",
"@webiny/cli-plugin-scaffold-graphql-service": "latest",
"@webiny/cli-plugin-scaffold-ci": "latest",
+ "@webiny/cli-plugin-scaffold-extensions": "latest",
"@webiny/cli-plugin-workspaces": "latest",
"@webiny/cli-plugin-deploy-pulumi": "latest",
"@webiny/project-utils": "latest",
@@ -50,14 +51,7 @@
"typescript": "4.7.4"
},
"workspaces": {
- "packages": [
- "apps/admin",
- "apps/website",
- "apps/theme",
- "apps/api/graphql",
- "apps/api/headlessCMS",
- "packages/*"
- ]
+ "packages": ["apps/admin", "apps/website", "apps/api/graphql", "extensions/theme", "packages/*"]
},
"scripts": {
"test": "jest --config jest.config.js --passWithNoTests",
diff --git a/packages/cwp-template-aws/template/ddb/apps/api/graphql/src/extensions.ts b/packages/cwp-template-aws/template/ddb/apps/api/graphql/src/extensions.ts
new file mode 100644
index 00000000000..658b605320b
--- /dev/null
+++ b/packages/cwp-template-aws/template/ddb/apps/api/graphql/src/extensions.ts
@@ -0,0 +1,4 @@
+// This file is automatically updated via scaffolding utilities.
+export const extensions = () => {
+ return [];
+};
diff --git a/packages/cwp-template-aws/template/ddb/apps/api/graphql/src/index.ts b/packages/cwp-template-aws/template/ddb/apps/api/graphql/src/index.ts
index a146c148387..ac96cd22ddd 100644
--- a/packages/cwp-template-aws/template/ddb/apps/api/graphql/src/index.ts
+++ b/packages/cwp-template-aws/template/ddb/apps/api/graphql/src/index.ts
@@ -39,6 +39,7 @@ import { createRecordLocking } from "@webiny/api-record-locking";
// Imports plugins created via scaffolding utilities.
import scaffoldsPlugins from "./plugins/scaffolds";
+import { extensions } from "./extensions";
const debug = process.env.DEBUG === "true";
@@ -103,7 +104,8 @@ export const handler = createHandler({
createAuditLogs(),
createAcoHcmsContext(),
createHcmsTasks(),
- scaffoldsPlugins()
+ scaffoldsPlugins(),
+ extensions()
],
debug
});
diff --git a/packages/cwp-template-aws/template/ddb/dependencies.json b/packages/cwp-template-aws/template/ddb/dependencies.json
index b4225c77b3f..2fd4a81b03a 100644
--- a/packages/cwp-template-aws/template/ddb/dependencies.json
+++ b/packages/cwp-template-aws/template/ddb/dependencies.json
@@ -8,6 +8,7 @@
"@webiny/cli-plugin-scaffold-admin-app-module": "latest",
"@webiny/cli-plugin-scaffold-graphql-service": "latest",
"@webiny/cli-plugin-scaffold-ci": "latest",
+ "@webiny/cli-plugin-scaffold-extensions": "latest",
"@webiny/cli-plugin-workspaces": "latest",
"@webiny/cli-plugin-deploy-pulumi": "latest",
"@webiny/project-utils": "latest",
@@ -49,14 +50,7 @@
"typescript": "4.7.4"
},
"workspaces": {
- "packages": [
- "apps/admin",
- "apps/website",
- "apps/theme",
- "apps/api/graphql",
- "apps/api/headlessCMS",
- "packages/*"
- ]
+ "packages": ["apps/admin", "apps/website", "apps/api/graphql", "extensions/theme", "packages/*"]
},
"scripts": {
"test": "jest --config jest.config.js --passWithNoTests",
diff --git a/scripts/prepublishOnly/src/prepublishOnly.ts b/scripts/prepublishOnly/src/prepublishOnly.ts
index d691f132242..29e3008b88e 100644
--- a/scripts/prepublishOnly/src/prepublishOnly.ts
+++ b/scripts/prepublishOnly/src/prepublishOnly.ts
@@ -135,7 +135,7 @@ const extraFiles: string[] = [
"packages/cwp-template-aws/template/ddb-es/apps/api/graphql/package.json",
"packages/cwp-template-aws/template/ddb-os/apps/api/graphql/package.json",
"packages/cwp-template-aws/template/common/apps/admin/package.json",
- "packages/cwp-template-aws/template/common/apps/theme/package.json",
+ "packages/cwp-template-aws/template/common/extensions/theme/package.json",
"packages/cwp-template-aws/template/common/apps/website/package.json"
];
diff --git a/webiny.project.ts b/webiny.project.ts
index e4f4f1e02e5..74a64bd04c0 100644
--- a/webiny.project.ts
+++ b/webiny.project.ts
@@ -19,6 +19,7 @@ export default {
import("@webiny/cli-plugin-scaffold"),
import("@webiny/cli-plugin-scaffold-graphql-service"),
import("@webiny/cli-plugin-scaffold-admin-app-module"),
+ import("@webiny/cli-plugin-scaffold-extensions"),
import("@webiny/cli-plugin-scaffold-ci")
]);
diff --git a/yarn.lock b/yarn.lock
index e7ffdc3664d..ec57e8fda7b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -14423,6 +14423,36 @@ __metadata:
languageName: unknown
linkType: soft
+"@webiny/api-serverless-cms@workspace:packages/api-serverless-cms":
+ version: 0.0.0-use.local
+ resolution: "@webiny/api-serverless-cms@workspace:packages/api-serverless-cms"
+ dependencies:
+ "@babel/cli": ^7.23.9
+ "@babel/core": ^7.24.0
+ "@babel/preset-env": ^7.24.0
+ "@babel/preset-typescript": ^7.23.3
+ "@webiny/api": 0.0.0
+ "@webiny/api-aco": 0.0.0
+ "@webiny/api-file-manager": 0.0.0
+ "@webiny/api-form-builder": 0.0.0
+ "@webiny/api-headless-cms": 0.0.0
+ "@webiny/api-i18n": 0.0.0
+ "@webiny/api-i18n-content": 0.0.0
+ "@webiny/api-page-builder": 0.0.0
+ "@webiny/api-page-builder-aco": 0.0.0
+ "@webiny/api-prerendering-service": 0.0.0
+ "@webiny/api-security": 0.0.0
+ "@webiny/api-tenancy": 0.0.0
+ "@webiny/cli": 0.0.0
+ "@webiny/handler-client": 0.0.0
+ "@webiny/handler-graphql": 0.0.0
+ "@webiny/project-utils": 0.0.0
+ rimraf: ^5.0.5
+ ttypescript: ^1.5.13
+ typescript: 4.7.4
+ languageName: unknown
+ linkType: soft
+
"@webiny/api-tenancy-so-ddb@0.0.0, @webiny/api-tenancy-so-ddb@workspace:packages/api-tenancy-so-ddb":
version: 0.0.0-use.local
resolution: "@webiny/api-tenancy-so-ddb@workspace:packages/api-tenancy-so-ddb"
@@ -16257,6 +16287,34 @@ __metadata:
languageName: unknown
linkType: soft
+"@webiny/cli-plugin-scaffold-extensions@workspace:packages/cli-plugin-scaffold-extensions":
+ version: 0.0.0-use.local
+ resolution: "@webiny/cli-plugin-scaffold-extensions@workspace:packages/cli-plugin-scaffold-extensions"
+ dependencies:
+ "@babel/cli": ^7.23.9
+ "@babel/core": ^7.24.0
+ "@babel/preset-env": ^7.24.0
+ "@types/inquirer": ^7.3.1
+ "@types/ncp": ^2.0.4
+ "@types/pluralize": ^0.0.29
+ "@types/validate-npm-package-name": ^3.0.3
+ "@webiny/cli": 0.0.0
+ "@webiny/cli-plugin-scaffold": 0.0.0
+ "@webiny/error": 0.0.0
+ "@webiny/project-utils": 0.0.0
+ case: ^1.6.3
+ execa: ^5.0.0
+ load-json-file: ^6.2.0
+ ncp: ^2.0.0
+ replace-in-path: ^1.1.0
+ rimraf: ^5.0.5
+ ts-morph: ^11.0.0
+ typescript: 4.7.4
+ validate-npm-package-name: ^3.0.0
+ write-json-file: ^4.3.0
+ languageName: unknown
+ linkType: soft
+
"@webiny/cli-plugin-scaffold-full-stack-app@workspace:packages/cli-plugin-scaffold-full-stack-app":
version: 0.0.0-use.local
resolution: "@webiny/cli-plugin-scaffold-full-stack-app@workspace:packages/cli-plugin-scaffold-full-stack-app"
@@ -37728,9 +37786,9 @@ __metadata:
languageName: node
linkType: hard
-"theme@^0.1.0, theme@workspace:apps/theme":
+"theme@^0.1.0, theme@workspace:extensions/theme":
version: 0.0.0-use.local
- resolution: "theme@workspace:apps/theme"
+ resolution: "theme@workspace:extensions/theme"
dependencies:
"@apollo/react-hooks": ^3.1.5
"@emotion/react": ^11.10.6