create-catalyst-app 1.1.0 → 1.2.0-canary.2
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.
- package/Readme.md +13 -0
- package/package.json +1 -1
- package/scripts/appIdentity.cjs +77 -0
- package/scripts/cli.cjs +13 -1
- package/scripts/generateDocs.cjs +6 -0
- package/templates/common/config/config.json +9 -0
- package/templates/common/public/android/splashscreen.png +0 -0
- package/templates/common/public/icon.png +0 -0
- package/templates/common/public/ios/splashscreen.png +0 -0
- package/templates/common/public/offline.html +46 -25
- package/templates/common/public/splashscreen.html +466 -0
- package/templates/common/server/index.js +36 -1
- package/templates/common/src/js/containers/Home/Home.js +119 -14
- package/templates/common/src/js/containers/Home/Home.scss +402 -18
- package/templates/common/src/js/containers/Home/Mark.js +82 -0
- package/templates/common/src/js/containers/Home/fonts/LICENSE-inter.txt +93 -0
- package/templates/common/src/js/containers/Home/fonts/LICENSE-jetbrains-mono.txt +93 -0
- package/templates/common/src/js/containers/Home/fonts/inter.woff2 +0 -0
- package/templates/common/src/js/containers/Home/fonts/jetbrains-mono.woff2 +0 -0
- package/templates/common/src/js/routes/index.js +4 -1
- package/templates/none-js/package.json +6 -2
- package/templates/none-ts/package.json +5 -1
- package/templates/redux-js/package.json +6 -2
- package/templates/redux-ts/package.json +5 -1
- package/templates/rtk-js/package.json +6 -2
- package/templates/rtk-ts/package.json +5 -1
- package/test/appIdentity.test.ts +142 -0
- package/test/errors.test.ts +40 -0
package/Readme.md
CHANGED
|
@@ -51,6 +51,19 @@ To serve the production build, execute:
|
|
|
51
51
|
npm run serve
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
## Android and iOS
|
|
55
|
+
|
|
56
|
+
Every app is ready to run as a native app. `config/config.json` gets `WEBVIEW_CONFIG.appId` (`com.example.<project name>`) and `appName` from the project name, and the app gets a placeholder `public/icon.png`.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm run android # run on an Android emulator or connected phone
|
|
60
|
+
npm run ios # run on an iOS simulator or connected iPhone (macOS)
|
|
61
|
+
npm run android:release # signed App Bundle for Google Play
|
|
62
|
+
npm run ios:release # signed IPA for App Store Connect
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The first run installs what is missing after asking. Before a release, replace the `com.example.` app id with your own and set `WEBVIEW_CONFIG.url` to your deployed site. See [Universal App Deployment](https://catalyst.1mg.com/content/Deployment/universal-app-deployment).
|
|
66
|
+
|
|
54
67
|
## Documentation
|
|
55
68
|
|
|
56
69
|
Explore the complete documentation at [https://catalyst.1mg.com](https://catalyst.1mg.com).
|
package/package.json
CHANGED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// The app id and name every new app gets in config/config.json, derived from
|
|
2
|
+
// the project name, so they are visible (and easy to change) from day one.
|
|
3
|
+
// A release build refuses the com.example.* id until it is replaced.
|
|
4
|
+
const fs = require("fs")
|
|
5
|
+
const path = require("path")
|
|
6
|
+
|
|
7
|
+
// Java keywords and literals cannot be package-name segments.
|
|
8
|
+
const JAVA_RESERVED = new Set(
|
|
9
|
+
(
|
|
10
|
+
"abstract assert boolean break byte case catch char class const continue default do double else enum " +
|
|
11
|
+
"extends false final finally float for goto if implements import instanceof int interface long native " +
|
|
12
|
+
"new null package private protected public return short static strictfp super switch synchronized this " +
|
|
13
|
+
"throw throws transient true try void volatile while"
|
|
14
|
+
).split(" ")
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
/** "@scope/my-shop" -> "com.example.myshop": valid on Android and iOS. */
|
|
18
|
+
function deriveAppId(projectName) {
|
|
19
|
+
const base = String(projectName || "")
|
|
20
|
+
.split("/")
|
|
21
|
+
.pop()
|
|
22
|
+
.toLowerCase()
|
|
23
|
+
.replace(/[^a-z0-9]/g, "")
|
|
24
|
+
let segment = base || "app"
|
|
25
|
+
if (/^[0-9]/.test(segment)) segment = `app${segment}`
|
|
26
|
+
if (JAVA_RESERVED.has(segment)) segment = `${segment}app`
|
|
27
|
+
return `com.example.${segment}`
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** "my-cool_app" -> "My Cool App": the name shown under the app icon. */
|
|
31
|
+
function deriveAppName(projectName) {
|
|
32
|
+
const words = String(projectName || "")
|
|
33
|
+
.split("/")
|
|
34
|
+
.pop()
|
|
35
|
+
.split(/[^A-Za-z0-9]+/)
|
|
36
|
+
.filter(Boolean)
|
|
37
|
+
if (words.length === 0) return "Catalyst App"
|
|
38
|
+
return words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Set WEBVIEW_CONFIG.appId and appName in the new app's config/config.json
|
|
43
|
+
* from the project name. The template carries both keys with placeholder
|
|
44
|
+
* values; only those two values change, so the file keeps its layout. A
|
|
45
|
+
* config without them gets them added under WEBVIEW_CONFIG.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} projectDir
|
|
48
|
+
* @param {string} projectName
|
|
49
|
+
* @returns {boolean} whether the file was written
|
|
50
|
+
*/
|
|
51
|
+
function applyAppIdentity(projectDir, projectName) {
|
|
52
|
+
const file = path.join(projectDir, "config", "config.json")
|
|
53
|
+
let text
|
|
54
|
+
let config
|
|
55
|
+
try {
|
|
56
|
+
text = fs.readFileSync(file, "utf8")
|
|
57
|
+
config = JSON.parse(text)
|
|
58
|
+
} catch {
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
const wv = config.WEBVIEW_CONFIG
|
|
62
|
+
if (!wv || typeof wv !== "object" || Array.isArray(wv)) return false
|
|
63
|
+
const appId = deriveAppId(projectName)
|
|
64
|
+
const appName = deriveAppName(projectName)
|
|
65
|
+
if (typeof wv.appId === "string" && typeof wv.appName === "string") {
|
|
66
|
+
text = text
|
|
67
|
+
.replace(/("appId"\s*:\s*)"[^"]*"/, `$1${JSON.stringify(appId)}`)
|
|
68
|
+
.replace(/("appName"\s*:\s*)"[^"]*"/, `$1${JSON.stringify(appName)}`)
|
|
69
|
+
} else {
|
|
70
|
+
config.WEBVIEW_CONFIG = { appId, appName, ...wv }
|
|
71
|
+
text = JSON.stringify(config, null, 4) + "\n"
|
|
72
|
+
}
|
|
73
|
+
fs.writeFileSync(file, text)
|
|
74
|
+
return true
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = { deriveAppId, deriveAppName, applyAppIdentity }
|
package/scripts/cli.cjs
CHANGED
|
@@ -21,6 +21,7 @@ const {
|
|
|
21
21
|
resolveOutputMode,
|
|
22
22
|
getDebugEnvInfo,
|
|
23
23
|
} = require("./errors.cjs")
|
|
24
|
+
const { applyAppIdentity } = require("./appIdentity.cjs")
|
|
24
25
|
const outputMode = resolveOutputMode(process.argv)
|
|
25
26
|
// Colored (red) prefix only applies in default mode — verbose/debug boxes
|
|
26
27
|
// own their coloring internally (see errors.cjs#box).
|
|
@@ -157,6 +158,8 @@ const program = new Commander.Command()
|
|
|
157
158
|
|
|
158
159
|
extractSubdirectory(packageFilePath)
|
|
159
160
|
createGitignore(projectName)
|
|
161
|
+
// appId and appName in config/config.json, from the project name.
|
|
162
|
+
applyAppIdentity(projectPath, projectName)
|
|
160
163
|
|
|
161
164
|
// npm's install output is hundreds of lines nobody reads
|
|
162
165
|
// when it works. Fold it behind a spinner, and print it in
|
|
@@ -568,7 +571,16 @@ function deleteDirectory(dirPath) {
|
|
|
568
571
|
|
|
569
572
|
// Function to create a .gitignore file with the hardcoded patterns
|
|
570
573
|
function createGitignore(projectName) {
|
|
571
|
-
|
|
574
|
+
// credentials/ holds signing keys, .catalyst/ per-machine CLI state, and
|
|
575
|
+
// build-output/ the signed store builds.
|
|
576
|
+
const gitiIgnorePatterns = [
|
|
577
|
+
"node_modules",
|
|
578
|
+
"build",
|
|
579
|
+
"logs",
|
|
580
|
+
"credentials/",
|
|
581
|
+
".catalyst/",
|
|
582
|
+
"build-output/",
|
|
583
|
+
]
|
|
572
584
|
|
|
573
585
|
const gitignorePath = `${process.cwd()}${path.sep}${projectName}${path.sep}.gitignore`
|
|
574
586
|
|
package/scripts/generateDocs.cjs
CHANGED
|
@@ -48,6 +48,12 @@ function generateDocs() {
|
|
|
48
48
|
// Merge into the shared errors/index.json rather than overwriting it —
|
|
49
49
|
// catalyst-core's own generateDocs.js owns every other category.
|
|
50
50
|
const index = readExistingIndex()
|
|
51
|
+
// Drop this package's own entries first, so a code removed from
|
|
52
|
+
// ERROR_DEFINITIONS does not linger in the index.
|
|
53
|
+
const ownedCategories = new Set(Object.values(ERROR_DEFINITIONS).map((d) => d.category))
|
|
54
|
+
for (const code of Object.keys(index)) {
|
|
55
|
+
if (ownedCategories.has(index[code].category)) delete index[code]
|
|
56
|
+
}
|
|
51
57
|
|
|
52
58
|
for (const [code, def] of Object.entries(ERROR_DEFINITIONS)) {
|
|
53
59
|
const dir = path.join(ERRORS_DIR, def.category)
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
"API_URL": "",
|
|
8
8
|
"CLIENT_ENV_VARIABLES": ["API_URL"],
|
|
9
9
|
"WEBVIEW_CONFIG": {
|
|
10
|
+
"appId": "com.example.app",
|
|
11
|
+
"appName": "Catalyst App",
|
|
10
12
|
"LOCAL_IP": "localhost",
|
|
11
13
|
"port": "3005",
|
|
12
14
|
"appInfo": "",
|
|
@@ -15,6 +17,13 @@
|
|
|
15
17
|
},
|
|
16
18
|
"ios": {
|
|
17
19
|
"buildType": "debug"
|
|
20
|
+
},
|
|
21
|
+
"splashScreen": {
|
|
22
|
+
"backgroundColor": "#0b0a14",
|
|
23
|
+
"minDuration": 7000,
|
|
24
|
+
"imageWidth": 144,
|
|
25
|
+
"imageHeight": 144,
|
|
26
|
+
"cornerRadius": 0
|
|
18
27
|
}
|
|
19
28
|
}
|
|
20
29
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -3,54 +3,75 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<meta name="color-scheme" content="light dark" />
|
|
6
7
|
<title>Offline</title>
|
|
7
8
|
<style>
|
|
9
|
+
:root {
|
|
10
|
+
--paper: #f5f4ff;
|
|
11
|
+
--ink: #14132a;
|
|
12
|
+
--muted: #4b4a6b;
|
|
13
|
+
--accent: #5353dc;
|
|
14
|
+
}
|
|
15
|
+
@media (prefers-color-scheme: dark) {
|
|
16
|
+
:root {
|
|
17
|
+
--paper: #0b0a14;
|
|
18
|
+
--ink: #f3f2ff;
|
|
19
|
+
--muted: #a9a8c9;
|
|
20
|
+
--accent: #a0a0ff;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
8
23
|
body {
|
|
9
24
|
margin: 0;
|
|
10
|
-
font-family:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
25
|
+
font-family:
|
|
26
|
+
system-ui,
|
|
27
|
+
-apple-system,
|
|
28
|
+
"Segoe UI",
|
|
29
|
+
sans-serif;
|
|
30
|
+
background: var(--paper);
|
|
31
|
+
color: var(--ink);
|
|
32
|
+
min-height: 100dvh;
|
|
14
33
|
display: flex;
|
|
15
34
|
align-items: center;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
font-
|
|
35
|
+
padding: 0 28px;
|
|
36
|
+
box-sizing: border-box;
|
|
37
|
+
-webkit-font-smoothing: antialiased;
|
|
19
38
|
}
|
|
20
39
|
.card {
|
|
21
|
-
display: flex;
|
|
22
|
-
flex-direction: column;
|
|
23
|
-
align-items: center;
|
|
24
|
-
gap: 12px;
|
|
25
|
-
padding: 0 24px;
|
|
26
40
|
max-width: 440px;
|
|
27
41
|
}
|
|
28
42
|
h1 {
|
|
29
43
|
margin: 0;
|
|
30
|
-
font-size:
|
|
31
|
-
font-weight:
|
|
44
|
+
font-size: clamp(2.5rem, 11vw, 3.5rem);
|
|
45
|
+
font-weight: 800;
|
|
46
|
+
line-height: 1.05;
|
|
47
|
+
letter-spacing: -0.04em;
|
|
32
48
|
}
|
|
33
49
|
p {
|
|
34
|
-
margin: 0;
|
|
35
|
-
color:
|
|
36
|
-
|
|
50
|
+
margin: 16px 0 0;
|
|
51
|
+
color: var(--muted);
|
|
52
|
+
font-size: 1.0625rem;
|
|
53
|
+
line-height: 1.5;
|
|
37
54
|
}
|
|
38
55
|
a.retry {
|
|
39
|
-
|
|
40
|
-
|
|
56
|
+
display: inline-block;
|
|
57
|
+
margin-top: 16px;
|
|
58
|
+
padding: 12px 0;
|
|
59
|
+
color: var(--accent);
|
|
60
|
+
font-weight: 650;
|
|
41
61
|
text-decoration: none;
|
|
42
|
-
transition: color 0.2s ease;
|
|
43
62
|
}
|
|
44
|
-
a.retry:
|
|
45
|
-
|
|
63
|
+
a.retry:focus-visible {
|
|
64
|
+
outline: 2px solid var(--accent);
|
|
65
|
+
outline-offset: 3px;
|
|
66
|
+
border-radius: 4px;
|
|
46
67
|
}
|
|
47
68
|
</style>
|
|
48
69
|
</head>
|
|
49
70
|
<body>
|
|
50
71
|
<div class="card">
|
|
51
|
-
<h1>You're
|
|
52
|
-
<p>
|
|
53
|
-
<a class="retry" href="catalyst://retry">Try
|
|
72
|
+
<h1>You're offline.</h1>
|
|
73
|
+
<p>Check your connection and try again.</p>
|
|
74
|
+
<a class="retry" href="catalyst://retry">Try again</a>
|
|
54
75
|
</div>
|
|
55
76
|
</body>
|
|
56
77
|
</html>
|