create-catalyst-app-internal 0.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/.prettierrc.json +7 -0
  2. package/package.json +21 -0
  3. package/scripts/cli.cjs +223 -0
  4. package/templates/common/.babelrc +26 -0
  5. package/templates/common/.eslintrc +53 -0
  6. package/templates/common/.prettierrc.json +7 -0
  7. package/templates/common/README.md +25 -0
  8. package/templates/common/api.js +27 -0
  9. package/templates/common/client/styles.js +14 -0
  10. package/templates/common/config/config.json +17 -0
  11. package/templates/common/server/document.js +14 -0
  12. package/templates/common/server/index.js +1 -0
  13. package/templates/common/server/server.js +1 -0
  14. package/templates/common/src/js/containers/Home/Home.js +23 -0
  15. package/templates/common/src/js/containers/Home/Home.scss +34 -0
  16. package/templates/common/src/js/routes/index.js +17 -0
  17. package/templates/common/src/js/routes/utils.js +29 -0
  18. package/templates/common/src/static/css/base/index.scss +1 -0
  19. package/templates/common/src/static/css/base/styles.scss +3 -0
  20. package/templates/common/src/static/css/resources/_variables.scss +0 -0
  21. package/templates/common/webpackConfig.js +5 -0
  22. package/templates/none-js/client/index.js +25 -0
  23. package/templates/none-js/package.json +23 -0
  24. package/templates/none-js/src/js/containers/App/index.js +14 -0
  25. package/templates/redux-js/client/index.js +28 -0
  26. package/templates/redux-js/package.json +25 -0
  27. package/templates/redux-js/src/js/containers/App/actions.js +17 -0
  28. package/templates/redux-js/src/js/containers/App/index.js +14 -0
  29. package/templates/redux-js/src/js/containers/App/reducer.js +21 -0
  30. package/templates/redux-js/src/js/store/index.js +28 -0
  31. package/templates/rtk-js/client/index.js +28 -0
  32. package/templates/rtk-js/package.json +25 -0
  33. package/templates/rtk-js/src/js/containers/App/index.js +14 -0
  34. package/templates/rtk-js/src/js/containers/App/reducer.js +18 -0
  35. package/templates/rtk-js/src/js/store/index.js +28 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "trailingComma": "es5",
3
+ "tabWidth": 4,
4
+ "semi": false,
5
+ "arrowParens": "always",
6
+ "printWidth": 110
7
+ }
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "create-catalyst-app-internal",
3
+ "bin": "scripts/cli.mjs",
4
+ "version": "0.0.1-beta.0",
5
+ "description": "cli package to scaffold Catalyst application",
6
+ "main": "index.js",
7
+ "scripts": {
8
+ "start": "node index.js"
9
+ },
10
+ "dependencies": {
11
+ "commander": "^8.2.0",
12
+ "fs": "^0.0.1-security",
13
+ "https": "^1.0.0",
14
+ "picocolors": "^0.1.0",
15
+ "prompts": "^2.4.0",
16
+ "tar": "6.1.15"
17
+ },
18
+ "devDependencies": {
19
+ "prettier": "^3.2.5"
20
+ }
21
+ }
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+ const { execSync } = require("child_process")
3
+ const Commander = require("commander")
4
+ const { Option } = require("commander")
5
+ const prompts = require("prompts")
6
+ const { red, green, cyan } = require("picocolors")
7
+
8
+ const packageJson = require("../package.json")
9
+ const tar = require("tar")
10
+ const path = require("path")
11
+ const fs = require("fs")
12
+
13
+ // Hardcoded branch
14
+ let projectName = null
15
+ const program = new Commander.Command()
16
+ .version(packageJson.version)
17
+ .description("Scaffolding")
18
+ .arguments("[folderName]")
19
+ .usage(`${green("[folderName]")} [options]`)
20
+ .action((name) => (projectName = name))
21
+ .addOption(
22
+ new Option(
23
+ "-s, --state-management [stateManagement]",
24
+ "Specify state management (rtk, redux, or none)",
25
+ /^(rtk|redux|none)$/i,
26
+ "none"
27
+ )
28
+ )
29
+ .action(async (folderName = null, cmd) => {
30
+ try {
31
+ // Use options provided through commander or prompt the user
32
+ validateOptions(cmd)
33
+ const projectName = folderName || (await promptProjectName())
34
+ const language = "js"
35
+ const projectDescription = await promptDescription()
36
+ const stateManagement = cmd.stateManagement || (await promptStateManagement())
37
+
38
+ const resolvedProjectPath = path.resolve(projectName.trim())
39
+ const projectPath = path.basename(resolvedProjectPath)
40
+ const root = path.resolve(projectPath)
41
+
42
+ // Define mapping of options to repository suffixes
43
+ const repositorySuffixes = {
44
+ js: "js",
45
+ ts: "ts",
46
+ redux: "redux",
47
+ rtk: "rtk",
48
+ none: "none",
49
+ }
50
+
51
+ const packageName = packageJson.name
52
+ const packageVersion = packageJson.version
53
+
54
+ const commonCodeDirectory = "package/templates/common"
55
+ const selectedTemplateCode = `package/templates/${repositorySuffixes[stateManagement]}-${repositorySuffixes[language]}`
56
+ const subDirectoriesToExtract = [commonCodeDirectory, selectedTemplateCode]
57
+ const extractionDestination = `/${projectName}/`
58
+ let tempDir
59
+ ;(() => {
60
+ try {
61
+ tempDir = createTempDir()
62
+
63
+ const packageFilePath = packNpmPackage(packageName, packageVersion, tempDir)
64
+
65
+ extractSubdirectory(packageFilePath)
66
+
67
+ execSync(
68
+ `cd ${projectName} && npm i && npm pkg set name=${projectName} ${
69
+ projectDescription ? `description=${projectDescription}` : ""
70
+ } && git init --quiet`,
71
+ { stdio: "inherit" }
72
+ )
73
+
74
+ console.log(cyan(`Installing Packages`))
75
+
76
+ deleteDirectory(tempDir)
77
+ } catch (error) {
78
+ deleteDirectory(tempDir)
79
+ console.error(`Error: ${error.message}`)
80
+ process.exit(1)
81
+ }
82
+ })()
83
+
84
+ function packNpmPackage(packageName, packageVersion, tempDir) {
85
+ const tarballFileName = `${packageName}-${packageVersion}.tgz`
86
+ const tarballFilePath = path.join(tempDir, tarballFileName)
87
+
88
+ try {
89
+ execSync(`npm pack ${packageName}@${packageVersion} --silent`, {
90
+ cwd: tempDir,
91
+ })
92
+
93
+ // to test locally, comment the upper execSync and uncomment this one.
94
+ // execSync(`npm pack --pack-destination=${tempDir} --silent`, {
95
+ // cwd: process.cwd(),
96
+ // });
97
+
98
+ return tarballFilePath
99
+ } catch (error) {
100
+ console.error(`Error packing npm package: ${error.message}`)
101
+ throw error
102
+ }
103
+ }
104
+
105
+ // Function to create a temporary directory
106
+ function createTempDir() {
107
+ const tempDir = fs.mkdtempSync(path.join(process.cwd(), "temp-"))
108
+
109
+ return tempDir
110
+ }
111
+
112
+ // Function to extract subdirectory from npm package and delete tar file
113
+ function extractSubdirectory(packageFilePath) {
114
+ try {
115
+ tar.extract({
116
+ file: packageFilePath,
117
+ sync: true,
118
+ filter: (path, entry) => {
119
+ return subDirectoriesToExtract.reduce((acc, item) => {
120
+ return acc || path.startsWith(item)
121
+ }, false)
122
+ },
123
+ cwd: path.join(process.cwd()),
124
+ onentry: (entry) => {
125
+ if (entry.path.startsWith(commonCodeDirectory)) {
126
+ entry.path = entry.path.replace(commonCodeDirectory, extractionDestination)
127
+ }
128
+ if (entry.path.startsWith(selectedTemplateCode)) {
129
+ entry.path = entry.path.replace(selectedTemplateCode, extractionDestination)
130
+ }
131
+ },
132
+ })
133
+ } catch (e) {
134
+ console.log("An error occurred", e)
135
+ }
136
+
137
+ cyan(`Run cd ${projectName} && npm start to get started.`)
138
+ }
139
+ } catch (error) {
140
+ console.error(red("An error occurred:"), error.message)
141
+ process.exit(1)
142
+ }
143
+ })
144
+ .allowUnknownOption()
145
+
146
+ program.parse(process.argv)
147
+
148
+ async function promptStateManagement() {
149
+ const response = await prompts({
150
+ type: "select",
151
+ name: "stateManagement",
152
+ message: "Choose state management:",
153
+ choices: [
154
+ { title: "Redux", value: "redux" },
155
+ { title: "Redux Toolkit (RTK)", value: "rtk" },
156
+ { title: "None", value: "none" },
157
+ ],
158
+ })
159
+
160
+ return response.stateManagement
161
+ }
162
+ async function promptProjectName() {
163
+ const res = await prompts({
164
+ type: "text",
165
+ name: "path",
166
+ message: "What is your project named?",
167
+ initial: "my-app",
168
+ })
169
+
170
+ if (typeof res.path === "string") {
171
+ let projectName = res.path.trim()
172
+ return projectName
173
+ }
174
+
175
+ if (!res.path || projectName === "") {
176
+ console.log(
177
+ "\nPlease specify the project directory:\n" +
178
+ ` ${cyan(program.name())} ${green("<project-directory>")}\n` +
179
+ "For example:\n" +
180
+ ` ${cyan(program.name())} ${green("my-next-app")}\n\n` +
181
+ `Run ${cyan(`${program.name()} --help`)} to see all options.`
182
+ )
183
+ process.exit(1)
184
+ }
185
+ }
186
+
187
+ async function promptDescription() {
188
+ const res = await prompts({
189
+ type: "text",
190
+ name: "path",
191
+ message: "What is your project description?",
192
+ })
193
+
194
+ if (typeof res.path === "string") {
195
+ return res.path.trim()
196
+ } else return null
197
+ }
198
+
199
+ function validateOptions(cmd) {
200
+ // Validate language option
201
+ if (cmd.lang && !["js", "ts"].includes(cmd.lang.toLowerCase())) {
202
+ throw new Error('Invalid language option. Use "js" or "ts".')
203
+ }
204
+
205
+ // Validate state management option
206
+ if (cmd.stateManagement && !["rtk", "redux", "none"].includes(cmd.stateManagement.toLowerCase())) {
207
+ throw new Error('Invalid state management option. Use "rtk", "redux", or "none".')
208
+ }
209
+ }
210
+
211
+ function deleteDirectory(dirPath) {
212
+ if (dirPath && fs.existsSync(dirPath)) {
213
+ fs.readdirSync(dirPath).forEach((file) => {
214
+ const currentPath = path.join(dirPath, file)
215
+ if (fs.lstatSync(currentPath).isDirectory()) {
216
+ deleteDirectory(currentPath)
217
+ } else {
218
+ fs.unlinkSync(currentPath)
219
+ }
220
+ })
221
+ fs.rmdirSync(dirPath)
222
+ }
223
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "presets": [
3
+ [
4
+ "@babel/preset-env",
5
+ {
6
+ "targets": {
7
+ "node": "current"
8
+ }
9
+ }
10
+ ],
11
+ "@babel/preset-react"
12
+ ],
13
+ "plugins": [
14
+ "@babel/plugin-proposal-object-rest-spread",
15
+ "transform-es2015-modules-commonjs",
16
+ "transform-class-properties",
17
+ "dynamic-import-node",
18
+ "@loadable/babel-plugin"
19
+ ],
20
+ "env": {
21
+ "test": {
22
+ "presets": ["@babel/preset-react"]
23
+ }
24
+ },
25
+ "ignore": ["__TEST__"]
26
+ }
@@ -0,0 +1,53 @@
1
+ {
2
+ "parser": "@babel/eslint-parser",
3
+ "rules": {
4
+ "prettier/prettier": "error",
5
+ "no-console": "warn",
6
+ "react/prop-types": 1,
7
+ "react/display-name": [0, { "ignoreTranspilerName": true }],
8
+ "react-hooks/exhaustive-deps": "warn", // Checks effect dependencies
9
+ "no-prototype-builtins": "off",
10
+ "jam3/no-sanitizer-with-danger": 2,
11
+ "react/jsx-no-target-blank": [0, {
12
+ "enforceDynamicLinks": "never"
13
+ }]
14
+ },
15
+ "env": {
16
+ "browser": true,
17
+ "es6": true,
18
+ "jest": true,
19
+ "node": true
20
+ },
21
+ "globals": {
22
+ "expect": true,
23
+ "__non_webpack_require__": true,
24
+ "logger": "readonly",
25
+ "AppCallbacks": "readonly"
26
+ },
27
+ "extends": ["eslint:recommended", "plugin:react/recommended"],
28
+ "parserOptions": {
29
+ "sourceType": "module",
30
+ "ecmaFeatures": {
31
+ "experimentalObjectRestSpread": true,
32
+ "jsx": true
33
+ },
34
+ "babelOptions": {
35
+ "configFile": "./babel.config.js"
36
+ },
37
+ "ecmaVersion": 6
38
+ },
39
+ "plugins": ["babel", "react", "react-hooks", "prettier", "jam3"],
40
+ "settings": {
41
+ "react": {
42
+ "createClass": "createReactClass",
43
+ "pragma": "React",
44
+ "version": "detect"
45
+ },
46
+ "propWrapperFunctions": [
47
+ "forbidExtraProps",
48
+ { "property": "freeze", "object": "Object" },
49
+ { "property": "myFavoriteWrapper" }
50
+ ],
51
+ "linkComponents": ["Hyperlink", { "name": "Link", "linkAttribute": "to" }]
52
+ }
53
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "trailingComma": "es5",
3
+ "tabWidth": 4,
4
+ "semi": false,
5
+ "arrowParens": "always",
6
+ "printWidth": 110
7
+ }
@@ -0,0 +1,25 @@
1
+ ## Getting Started
2
+
3
+ Commence development by initiating the application in development mode with the following commands:
4
+
5
+ For running the application in development mode, run:
6
+
7
+ ```bash
8
+ npm run start
9
+ ```
10
+
11
+ For a production build, utilize:
12
+
13
+ ```bash
14
+ npm run build
15
+ ```
16
+
17
+ To serve the production build, execute:
18
+
19
+ ```bash
20
+ npm run serve
21
+ ```
22
+
23
+ ## Documentation
24
+
25
+ Explore the complete documentation at [https://catalyst.1mg.com](https://catalyst.1mg.com).
@@ -0,0 +1,27 @@
1
+ const apiInstance = () => {
2
+ const fetchFunction = async (url, options) => {
3
+ let baseURL = process.env.API_URL
4
+ let finalUrl = baseURL + url
5
+
6
+ // Request Interceptor - you can modify request here
7
+
8
+ // Add query params if exist
9
+ if (Object.keys(options?.params).length > 0) {
10
+ finalUrl = url + "?" + new URLSearchParams(options.params)
11
+ }
12
+
13
+ return fetch(finalUrl, options).then(async (response) => {
14
+ const parsedResponse = await response.json()
15
+ // Response Interceptor - you can modify response here
16
+ return parsedResponse
17
+ })
18
+ }
19
+ return {
20
+ get: fetchFunction,
21
+ post: fetchFunction,
22
+ delete: fetchFunction,
23
+ patch: fetchFunction,
24
+ put: fetchFunction,
25
+ }
26
+ }
27
+ export default { apiInstance }
@@ -0,0 +1,14 @@
1
+ /* Style Loader
2
+ *
3
+ * Anything imported in here will either be added to the vendor CSS chunk, or
4
+ * the main app CSS chunk. Where they will go depends on its location or its
5
+ * extension.
6
+ *
7
+ * Files will be added to the vendor.css chunk if:
8
+ * - they are located inside `node_modules`, or
9
+ * - they are plain .css files.
10
+ * Otherwise, files will be added to the main app.css chunk.
11
+ */
12
+
13
+ // Include initial base styles.
14
+ import "@css/base/index.scss"
@@ -0,0 +1,17 @@
1
+ {
2
+ "NODE_SERVER_HOSTNAME": "localhost",
3
+ "NODE_SERVER_PORT": 3005,
4
+ "WEBPACK_DEV_SERVER_HOSTNAME": "localhost",
5
+ "WEBPACK_DEV_SERVER_PORT": 3006,
6
+ "BUILD_OUTPUT_PATH": "build",
7
+ "PUBLIC_STATIC_ASSET_PATH": "/assets/",
8
+ "PUBLIC_STATIC_ASSET_URL": "http://localhost:3006",
9
+ "NODE_ENV": "production",
10
+ "BUILD_ENV": "localBuild",
11
+ "API_URL": "",
12
+ "CLIENT_EXPOSED_KEYS": [],
13
+ "ANALYZE_BUNDLE": false,
14
+ "ENABLE_DEBUG_LOGS": true,
15
+ "ENABLE_FILE_LOGGING": true,
16
+ "ENABLE_CONSOLE_LOGGING": true
17
+ }
@@ -0,0 +1,14 @@
1
+ import React from "react"
2
+ import { Head, Body } from "catalyst-core-internal"
3
+
4
+ function Document(props) {
5
+ return (
6
+ <html lang={props.lang}>
7
+ <Head {...props}>
8
+ <meta charset="final-order" />
9
+ </Head>
10
+ <Body {...props} />
11
+ </html>
12
+ )
13
+ }
14
+ export default Document
@@ -0,0 +1 @@
1
+ export const preServerInit = () => {}
@@ -0,0 +1 @@
1
+ export function addMiddlewares(app) {}
@@ -0,0 +1,23 @@
1
+ import React from "react"
2
+ import css from "./Home.scss"
3
+
4
+ function Landing() {
5
+ return (
6
+ <div className={css.app}>
7
+ <header className={css.appHeader}>
8
+ <h1 className={css.heading}>Catalyst</h1>
9
+ <p>Edit files inside src directory and save to reload.</p>
10
+ <a
11
+ className={css.appLink}
12
+ href="https://catalyst.1mg.com"
13
+ target="_blank"
14
+ rel="noopener noreferrer"
15
+ >
16
+ Learn Catalyst
17
+ </a>
18
+ </header>
19
+ </div>
20
+ )
21
+ }
22
+
23
+ export default Landing
@@ -0,0 +1,34 @@
1
+ body {
2
+ margin: 0;
3
+ }
4
+
5
+ .app {
6
+ text-align: center;
7
+ margin: 0;
8
+ }
9
+
10
+ .appLogo {
11
+ height: 40vmin;
12
+ pointer-events: none;
13
+ }
14
+
15
+ @media (prefers-reduced-motion: no-preference) {
16
+ .appLogo {
17
+ animation: App-logo-spin infinite 20s linear;
18
+ }
19
+ }
20
+
21
+ .appHeader {
22
+ background-color: #282c34;
23
+ min-height: 100vh;
24
+ display: flex;
25
+ flex-direction: column;
26
+ align-items: center;
27
+ justify-content: center;
28
+ font-size: calc(10px + 2vmin);
29
+ color: white;
30
+ }
31
+
32
+ .appLink {
33
+ color: #61dafb;
34
+ }
@@ -0,0 +1,17 @@
1
+ import Home from "@containers/Home/Home"
2
+
3
+ const routes = [
4
+ {
5
+ path: "/",
6
+ end: true,
7
+ component: Home,
8
+ },
9
+ ]
10
+
11
+ /**
12
+ * Making the routes array compatible with the format accepted by createBrowserRouter
13
+ * API on the client side
14
+ * https://reactrouter.com/en/main/routers/create-browser-router
15
+ */
16
+
17
+ export default routes
@@ -0,0 +1,29 @@
1
+ import React from "react"
2
+ import { RouterDataProvider, MetaTag } from "@tata1mg/router"
3
+ import App from "@containers/App"
4
+ import routes from "./index.js"
5
+
6
+ export const preparedRoutes = ({ store, routerInitialState }) => {
7
+ return [
8
+ {
9
+ element: (
10
+ <RouterDataProvider config={{}} initialState={routerInitialState} fetcherArgs={{ store }}>
11
+ <MetaTag />
12
+ <App />
13
+ </RouterDataProvider>
14
+ ),
15
+ children: getRoutes()?.map((route, index) => {
16
+ const Component = route.component
17
+ // const pageType = route.staticPageType ? route.staticPageType : null
18
+ return {
19
+ ...route,
20
+ element: <Component key={index} />,
21
+ }
22
+ }),
23
+ },
24
+ ]
25
+ }
26
+
27
+ export const getRoutes = () => {
28
+ return routes
29
+ }
@@ -0,0 +1 @@
1
+ @import "styles";
@@ -0,0 +1,3 @@
1
+ html {
2
+ box-sizing: border-box;
3
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ developmentPlugins: [],
3
+ ssrPlugins: [],
4
+ clientPlugins: [],
5
+ }
@@ -0,0 +1,25 @@
1
+ import React from "react"
2
+ import "./styles"
3
+ import { hydrateRoot } from "react-dom/client"
4
+ import { loadableReady } from "@loadable/component"
5
+ import { RouterProvider } from "@tata1mg/router"
6
+ import clientRouter from "catalyst-core-internal/router/ClientRouter"
7
+
8
+ window.addEventListener("load", () => {
9
+ loadableReady(() => {
10
+ const { __ROUTER_INITIAL_DATA__: routerInitialData, __INITIAL_STATE__ } = window
11
+
12
+ const router = clientRouter({ routerInitialState: routerInitialData })
13
+
14
+ const Application = (
15
+ <Provider serverState={__INITIAL_STATE__}>
16
+ <React.StrictMode>
17
+ <RouterProvider router={router} />
18
+ </React.StrictMode>
19
+ </Provider>
20
+ )
21
+
22
+ const container = document.getElementById("app")
23
+ hydrateRoot(container, Application)
24
+ })
25
+ })
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "create-catalyst-app-starter",
3
+ "version": "1.0.0",
4
+ "scripts": {
5
+ "start": "catalyst start",
6
+ "build": "catalyst build",
7
+ "serve": "catalyst serve"
8
+ },
9
+ "_moduleAliases": {
10
+ "@api": "api.js",
11
+ "@containers": "src/js/containers",
12
+ "@server": "server",
13
+ "@config": "config",
14
+ "@css": "src/static/css",
15
+ "@routes": "src/js/routes/",
16
+ "@store": "src/js/store/index.js"
17
+ },
18
+ "dependencies": {
19
+ "@loadable/component": "^5.16.3",
20
+ "@tata1mg/router": "^0.0.1-alpha.13",
21
+ "catalyst-core-internal": "0.0.1-beta.0"
22
+ }
23
+ }
@@ -0,0 +1,14 @@
1
+ import React, { useState } from "react"
2
+ import { useOutlet } from "@tata1mg/router"
3
+ const App = () => {
4
+ const o = useOutlet()
5
+ const [outlet] = useState(o)
6
+
7
+ return <>{outlet}</>
8
+ }
9
+
10
+ App.serverSideFunction = ({}) => {
11
+ return new Promise((resolve) => resolve())
12
+ }
13
+
14
+ export default App
@@ -0,0 +1,28 @@
1
+ import React from "react"
2
+ import "./styles"
3
+ import { hydrateRoot } from "react-dom/client"
4
+ import { loadableReady } from "@loadable/component"
5
+ import { Provider } from "react-redux"
6
+ import { RouterProvider } from "@tata1mg/router"
7
+ import clientRouter from "catalyst-core-internal/router/ClientRouter"
8
+ import configureStore from "@store"
9
+
10
+ window.addEventListener("load", () => {
11
+ loadableReady(() => {
12
+ const { __ROUTER_INITIAL_DATA__: routerInitialData, __INITIAL_STATE__ } = window
13
+ const store = configureStore(__INITIAL_STATE__ || {})
14
+
15
+ const router = clientRouter({ store, routerInitialState: routerInitialData })
16
+
17
+ const Application = (
18
+ <Provider store={store} serverState={__INITIAL_STATE__}>
19
+ <React.StrictMode>
20
+ <RouterProvider router={router} />
21
+ </React.StrictMode>
22
+ </Provider>
23
+ )
24
+
25
+ const container = document.getElementById("app")
26
+ hydrateRoot(container, Application)
27
+ })
28
+ })
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "create-catalyst-app-starter",
3
+ "version": "1.0.0",
4
+ "scripts": {
5
+ "start": "catalyst start",
6
+ "build": "catalyst build",
7
+ "serve": "catalyst serve"
8
+ },
9
+ "_moduleAliases": {
10
+ "@api": "api.js",
11
+ "@containers": "src/js/containers",
12
+ "@server": "server",
13
+ "@config": "config",
14
+ "@css": "src/static/css",
15
+ "@routes": "src/js/routes/",
16
+ "@store": "src/js/store/index.js"
17
+ },
18
+ "dependencies": {
19
+ "@loadable/component": "^5.16.3",
20
+ "@tata1mg/router": "^0.0.1-alpha.13",
21
+ "catalyst-core-internal": "0.0.1-beta.0",
22
+ "@reduxjs/toolkit": "1.9.3",
23
+ "react-redux": "^8.1.3"
24
+ }
25
+ }
@@ -0,0 +1,17 @@
1
+ const createActionTypes = (prefix, actionTypeList = []) => {
2
+ const actionTypesObject = {}
3
+ actionTypeList.forEach((item) => {
4
+ actionTypesObject[item] = `${prefix}/${item}`
5
+ })
6
+
7
+ return actionTypesObject
8
+ }
9
+
10
+ export default createActionTypes
11
+
12
+ export const ShellActions = createActionTypes("shellActions", ["REDUX_TEST"])
13
+ export const reduxTest = () => {
14
+ return {
15
+ type: ShellActions.REDUX_TEST,
16
+ }
17
+ }
@@ -0,0 +1,14 @@
1
+ import React, { useState } from "react"
2
+ import { useOutlet } from "@tata1mg/router"
3
+ const App = () => {
4
+ const o = useOutlet()
5
+ const [outlet] = useState(o)
6
+
7
+ return <>{outlet}</>
8
+ }
9
+
10
+ App.serverSideFunction = () => {
11
+ return new Promise((resolve) => resolve())
12
+ }
13
+
14
+ export default App
@@ -0,0 +1,21 @@
1
+ import { ShellActions } from "./actions"
2
+
3
+ export const defaultState = {
4
+ testActionDispatched: false,
5
+ }
6
+
7
+ const shellReducer = (state = defaultState, action) => {
8
+ switch (action.type) {
9
+ case ShellActions.REDUX_TEST: {
10
+ return {
11
+ ...state,
12
+ testActionDispatched: true,
13
+ }
14
+ }
15
+
16
+ default:
17
+ return state
18
+ }
19
+ }
20
+
21
+ export default shellReducer
@@ -0,0 +1,28 @@
1
+ import { configureStore as createStore } from "@reduxjs/toolkit"
2
+ import { combineReducers } from "redux"
3
+ import { shellReducer } from "@containers/App/reducer.js"
4
+ import fetchInstance from "@api"
5
+
6
+ /**
7
+ * Function that initializes the store with the initialstate and adds middlewares that can be used during action dispatch
8
+ * @param {object} initialState Default state
9
+ * @param {object} request Request object that we recieve on server, this is only recieved when store is initialised on the server.
10
+ * @return {object} The store itself
11
+ */
12
+
13
+ const configureStore = (initialState, request) => {
14
+ const api = fetchInstance
15
+ const store = createStore({
16
+ reducer: combineReducers({ shellReducer }),
17
+ middleware: (getDefaultMiddleware) =>
18
+ getDefaultMiddleware({
19
+ thunk: {
20
+ extraArgument: { api },
21
+ },
22
+ }),
23
+ preloadedState: initialState,
24
+ })
25
+ return store
26
+ }
27
+
28
+ export default configureStore
@@ -0,0 +1,28 @@
1
+ import React from "react"
2
+ import "./styles"
3
+ import { hydrateRoot } from "react-dom/client"
4
+ import { loadableReady } from "@loadable/component"
5
+ import { Provider } from "react-redux"
6
+ import { RouterProvider } from "@tata1mg/router"
7
+ import clientRouter from "catalyst-core-internal/router/ClientRouter"
8
+ import configureStore from "@store"
9
+
10
+ window.addEventListener("load", () => {
11
+ loadableReady(() => {
12
+ const { __ROUTER_INITIAL_DATA__: routerInitialData, __INITIAL_STATE__ } = window
13
+ const store = configureStore(__INITIAL_STATE__ || {})
14
+
15
+ const router = clientRouter({ store, routerInitialState: routerInitialData })
16
+
17
+ const Application = (
18
+ <Provider store={store} serverState={__INITIAL_STATE__}>
19
+ <React.StrictMode>
20
+ <RouterProvider router={router} />
21
+ </React.StrictMode>
22
+ </Provider>
23
+ )
24
+
25
+ const container = document.getElementById("app")
26
+ hydrateRoot(container, Application)
27
+ })
28
+ })
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "create-catalyst-app-starter",
3
+ "version": "1.0.0",
4
+ "scripts": {
5
+ "start": "catalyst start",
6
+ "build": "catalyst build",
7
+ "serve": "catalyst serve"
8
+ },
9
+ "_moduleAliases": {
10
+ "@api": "api.js",
11
+ "@containers": "src/js/containers",
12
+ "@server": "server",
13
+ "@config": "config",
14
+ "@css": "src/static/css",
15
+ "@routes": "src/js/routes/",
16
+ "@store": "src/js/store/index.js"
17
+ },
18
+ "dependencies": {
19
+ "@loadable/component": "^5.16.3",
20
+ "@tata1mg/router": "^0.0.1-alpha.13",
21
+ "catalyst-core-internal": "0.0.1-beta.0",
22
+ "@reduxjs/toolkit": "1.9.3",
23
+ "react-redux": "^8.1.3"
24
+ }
25
+ }
@@ -0,0 +1,14 @@
1
+ import React, { useState } from "react"
2
+ import { useOutlet } from "@tata1mg/router"
3
+ const App = () => {
4
+ const o = useOutlet()
5
+ const [outlet] = useState(o)
6
+
7
+ return <>{outlet}</>
8
+ }
9
+
10
+ App.serverSideFunction = () => {
11
+ return new Promise((resolve) => resolve())
12
+ }
13
+
14
+ export default App
@@ -0,0 +1,18 @@
1
+ import { createSlice } from "@reduxjs/toolkit"
2
+
3
+ const initialState = {
4
+ testActionDispatched: false,
5
+ }
6
+
7
+ export const appSlice = createSlice({
8
+ name: "shellReducer",
9
+ initialState: initialState,
10
+ reducers: {
11
+ reduxTest: (state, action) => {
12
+ state.testActionDispatched = true
13
+ },
14
+ },
15
+ })
16
+
17
+ export const { reduxTest } = appSlice.actions
18
+ export const shellReducer = appSlice.reducer
@@ -0,0 +1,28 @@
1
+ import { configureStore as createStore } from "@reduxjs/toolkit"
2
+ import { combineReducers } from "redux"
3
+ import { shellReducer } from "@containers/App/reducer.js"
4
+ import fetchInstance from "@api"
5
+
6
+ /**
7
+ * Function that initializes the store with the initialstate and adds middlewares that can be used during action dispatch
8
+ * @param {object} initialState Default state
9
+ * @param {object} request Request object that we recieve on server, this is only recieved when store is initialised on the server.
10
+ * @return {object} The store itself
11
+ */
12
+
13
+ const configureStore = (initialState, request) => {
14
+ const api = fetchInstance
15
+ const store = createStore({
16
+ reducer: combineReducers({ shellReducer }),
17
+ middleware: (getDefaultMiddleware) =>
18
+ getDefaultMiddleware({
19
+ thunk: {
20
+ extraArgument: { api },
21
+ },
22
+ }),
23
+ preloadedState: initialState,
24
+ })
25
+ return store
26
+ }
27
+
28
+ export default configureStore