@bleedingdev/modern-js-create 3.2.0-ultramodern.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.
- package/LICENSE +21 -0
- package/README.md +112 -0
- package/bin/run.js +73 -0
- package/dist/index.js +2320 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/locale/en.d.ts +55 -0
- package/dist/types/locale/index.d.ts +112 -0
- package/dist/types/locale/zh.d.ts +55 -0
- package/dist/types/ultramodern-workspace.d.ts +20 -0
- package/package.json +56 -0
- package/template/.browserslistrc +4 -0
- package/template/.github/workflows/ultramodern-gates.yml.handlebars +30 -0
- package/template/.gitignore.handlebars +30 -0
- package/template/.nvmrc +2 -0
- package/template/README.md +78 -0
- package/template/api/effect/index.ts.handlebars +61 -0
- package/template/api/lambda/hello.ts.handlebars +6 -0
- package/template/biome.json +41 -0
- package/template/modern.config.ts.handlebars +50 -0
- package/template/package.json.handlebars +47 -0
- package/template/postcss.config.mjs.handlebars +6 -0
- package/template/scripts/validate-ultramodern.mjs.handlebars +102 -0
- package/template/shared/effect/api.ts.handlebars +18 -0
- package/template/src/modern-app-env.d.ts +1 -0
- package/template/src/modern.runtime.ts.handlebars +9 -0
- package/template/src/routes/index.css.handlebars +118 -0
- package/template/src/routes/layout.tsx.handlebars +9 -0
- package/template/src/routes/page.tsx.handlebars +119 -0
- package/template/tailwind.config.ts.handlebars +10 -0
- package/template/tsconfig.json +16 -0
- package/template-workspace/README.md.handlebars +28 -0
- package/template-workspace/pnpm-workspace.yaml +5 -0
- package/template-workspace/scripts/validate-ultramodern-workspace.mjs.handlebars +276 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
const configPath = path.resolve(process.cwd(), 'modern.config.ts');
|
|
5
|
+
const templateManifestPath = path.resolve(
|
|
6
|
+
process.cwd(),
|
|
7
|
+
'.modernjs/mv-template-manifest.json',
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
if (!fs.existsSync(configPath)) {
|
|
11
|
+
console.error('modern.config.ts not found');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
16
|
+
const requiredTokens = [
|
|
17
|
+
'presetUltramodern(',
|
|
18
|
+
'appTools()',
|
|
19
|
+
'enableModuleFederationSSR',
|
|
20
|
+
'enableBffRequestId',
|
|
21
|
+
'enableTelemetryExporters',
|
|
22
|
+
];
|
|
23
|
+
const missing = requiredTokens.filter(token => !content.includes(token));
|
|
24
|
+
|
|
25
|
+
if (missing.length > 0) {
|
|
26
|
+
console.error(
|
|
27
|
+
`Ultramodern contract check failed. Missing tokens: ${missing.join(', ')}`,
|
|
28
|
+
);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!fs.existsSync(templateManifestPath)) {
|
|
33
|
+
console.error('.modernjs/mv-template-manifest.json not found');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const templateManifest = JSON.parse(
|
|
38
|
+
fs.readFileSync(templateManifestPath, 'utf8'),
|
|
39
|
+
);
|
|
40
|
+
const requiredDeniedPaths = [
|
|
41
|
+
'.git/**',
|
|
42
|
+
'.github/**',
|
|
43
|
+
'.npmrc',
|
|
44
|
+
'.yarnrc',
|
|
45
|
+
'.env',
|
|
46
|
+
'.env.*',
|
|
47
|
+
'node_modules/**',
|
|
48
|
+
'dist/**',
|
|
49
|
+
];
|
|
50
|
+
const requiredPostMaterialization = [
|
|
51
|
+
'ultramodern-contract-check',
|
|
52
|
+
'dependency-install-with-lifecycle-deny',
|
|
53
|
+
'template-manifest-retained',
|
|
54
|
+
];
|
|
55
|
+
const manifestErrors = [];
|
|
56
|
+
|
|
57
|
+
if (templateManifest.schemaVersion !== 1) {
|
|
58
|
+
manifestErrors.push('schemaVersion');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (templateManifest.source?.type !== 'builtin') {
|
|
62
|
+
manifestErrors.push('source.type');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (
|
|
66
|
+
!Array.isArray(templateManifest.integrity?.checksums) ||
|
|
67
|
+
!templateManifest.integrity.checksums.some(
|
|
68
|
+
checksum =>
|
|
69
|
+
checksum.algorithm === 'sha256' &&
|
|
70
|
+
checksum.scope === 'source-tree' &&
|
|
71
|
+
/^[0-9a-f]{64}$/.test(checksum.value),
|
|
72
|
+
)
|
|
73
|
+
) {
|
|
74
|
+
manifestErrors.push('integrity.checksums[source-tree]');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
for (const deniedPath of requiredDeniedPaths) {
|
|
78
|
+
if (!templateManifest.materialization?.deniedPaths?.includes(deniedPath)) {
|
|
79
|
+
manifestErrors.push(`materialization.deniedPaths:${deniedPath}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (templateManifest.lifecyclePolicy?.denyByDefault !== true) {
|
|
84
|
+
manifestErrors.push('lifecyclePolicy.denyByDefault');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
for (const token of requiredPostMaterialization) {
|
|
88
|
+
if (!templateManifest.validation?.postMaterializationValidation?.includes(token)) {
|
|
89
|
+
manifestErrors.push(`validation.postMaterializationValidation:${token}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (manifestErrors.length > 0) {
|
|
94
|
+
console.error(
|
|
95
|
+
`Ultramodern template manifest check failed. Invalid fields: ${manifestErrors.join(
|
|
96
|
+
', ',
|
|
97
|
+
)}`,
|
|
98
|
+
);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log('Ultramodern contract check passed.');
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{{#if useEffectBff}}import {
|
|
2
|
+
HttpApi,
|
|
3
|
+
HttpApiEndpoint,
|
|
4
|
+
HttpApiGroup,
|
|
5
|
+
Schema,
|
|
6
|
+
} from '@modern-js/plugin-bff/effect-client';
|
|
7
|
+
|
|
8
|
+
export const bffEffectApi = HttpApi.make('BffApi').add(
|
|
9
|
+
HttpApiGroup.make('greetings').add(
|
|
10
|
+
HttpApiEndpoint.get('hello', '/effect/hello', {
|
|
11
|
+
success: Schema.Struct({
|
|
12
|
+
message: Schema.String,
|
|
13
|
+
runtime: Schema.Literal('effect'),
|
|
14
|
+
}),
|
|
15
|
+
}),
|
|
16
|
+
),
|
|
17
|
+
);
|
|
18
|
+
{{/if}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types='@modern-js/app-tools/types' />
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
{{#if enableTailwind}}@import 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
{{/if}}html,
|
|
4
|
+
body {
|
|
5
|
+
padding: 0;
|
|
6
|
+
margin: 0;
|
|
7
|
+
font-family: PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
|
|
8
|
+
background: linear-gradient(to bottom, transparent, #fff) #eceeef;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
p {
|
|
12
|
+
margin: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
* {
|
|
16
|
+
-webkit-font-smoothing: antialiased;
|
|
17
|
+
-moz-osx-font-smoothing: grayscale;
|
|
18
|
+
box-sizing: border-box;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.container-box {
|
|
22
|
+
min-height: 100vh;
|
|
23
|
+
max-width: 100%;
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
justify-content: center;
|
|
27
|
+
align-items: center;
|
|
28
|
+
padding-top: 10px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
main {
|
|
32
|
+
flex: 1;
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
justify-content: center;
|
|
36
|
+
align-items: center;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.title {
|
|
40
|
+
display: flex;
|
|
41
|
+
margin: 4rem 0 4rem;
|
|
42
|
+
align-items: center;
|
|
43
|
+
font-size: 4rem;
|
|
44
|
+
font-weight: 600;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.logo {
|
|
48
|
+
width: 6rem;
|
|
49
|
+
margin: 7px 0 0 1rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.name {
|
|
53
|
+
color: #4ecaff;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.description {
|
|
57
|
+
text-align: center;
|
|
58
|
+
line-height: 1.5;
|
|
59
|
+
font-size: 1.3rem;
|
|
60
|
+
color: #1b3a42;
|
|
61
|
+
margin-bottom: 5rem;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.code {
|
|
65
|
+
background: #fafafa;
|
|
66
|
+
border-radius: 12px;
|
|
67
|
+
padding: 0.6rem 0.9rem;
|
|
68
|
+
font-size: 1.05rem;
|
|
69
|
+
font-family:
|
|
70
|
+
Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
|
71
|
+
Bitstream Vera Sans Mono, Courier New, monospace;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.container-box .grid {
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
justify-content: center;
|
|
78
|
+
width: 1100px;
|
|
79
|
+
margin-top: 3rem;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.card {
|
|
83
|
+
padding: 1.5rem;
|
|
84
|
+
display: flex;
|
|
85
|
+
flex-direction: column;
|
|
86
|
+
justify-content: center;
|
|
87
|
+
height: 100px;
|
|
88
|
+
color: inherit;
|
|
89
|
+
text-decoration: none;
|
|
90
|
+
transition: 0.15s ease;
|
|
91
|
+
width: 45%;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.card:hover,
|
|
95
|
+
.card:focus {
|
|
96
|
+
transform: scale(1.05);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.card h2 {
|
|
100
|
+
display: flex;
|
|
101
|
+
align-items: center;
|
|
102
|
+
font-size: 1.5rem;
|
|
103
|
+
margin: 0;
|
|
104
|
+
padding: 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.card p {
|
|
108
|
+
opacity: 0.6;
|
|
109
|
+
font-size: 0.9rem;
|
|
110
|
+
line-height: 1.5;
|
|
111
|
+
margin-top: 1rem;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.arrow-right {
|
|
115
|
+
width: 1.3rem;
|
|
116
|
+
margin-left: 0.5rem;
|
|
117
|
+
margin-top: 3px;
|
|
118
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Helmet } from '@modern-js/runtime/head';
|
|
2
|
+
{{#if useEffectBff}}import effectBff from '@api/effect/index';
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
{{/if}}
|
|
5
|
+
import './index.css';
|
|
6
|
+
|
|
7
|
+
const Index = () => {
|
|
8
|
+
{{#if useEffectBff}}
|
|
9
|
+
const [effectMessage, setEffectMessage] = useState('loading...');
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
effectBff.client.greetings.hello({}).then(data => {
|
|
13
|
+
setEffectMessage(data.message);
|
|
14
|
+
});
|
|
15
|
+
}, []);
|
|
16
|
+
{{/if}}
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className="container-box">
|
|
20
|
+
<Helmet>
|
|
21
|
+
<link
|
|
22
|
+
rel="icon"
|
|
23
|
+
type="image/x-icon"
|
|
24
|
+
href="https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/favicon.ico"
|
|
25
|
+
/>
|
|
26
|
+
</Helmet>
|
|
27
|
+
<main>
|
|
28
|
+
<div className="title">
|
|
29
|
+
Modern.js
|
|
30
|
+
<img
|
|
31
|
+
className="logo"
|
|
32
|
+
src="https://lf3-static.bytednsdoc.com/obj/eden-cn/zq-uylkvT/ljhwZthlaukjlkulzlp/modern-js-logo.svg"
|
|
33
|
+
alt="Modern.js Logo"
|
|
34
|
+
/>
|
|
35
|
+
<p className="name">presetUltramodern</p>
|
|
36
|
+
</div>
|
|
37
|
+
<p className="description{{#if enableTailwind}} text-emerald-700 font-semibold{{/if}}">
|
|
38
|
+
This starter ships the public <code className="code">presetUltramodern(...)</code> profile. Start in
|
|
39
|
+
<code className="code">modern.config.ts</code>, keep
|
|
40
|
+
<code className="code">pnpm run ultramodern:check</code> green, and
|
|
41
|
+
tune the generated preset only where your app needs a softer lane.
|
|
42
|
+
</p>
|
|
43
|
+
{{#if useEffectBff}}
|
|
44
|
+
<p className="description effect-message{{#if enableTailwind}} text-emerald-700 font-semibold{{/if}}">
|
|
45
|
+
Effect HttpApi response: <code className="code">{effectMessage}</code>
|
|
46
|
+
</p>
|
|
47
|
+
{{/if}}
|
|
48
|
+
<div className="grid">
|
|
49
|
+
<a
|
|
50
|
+
href="https://modernjs.dev/en/guides/get-started/ultramodern.html"
|
|
51
|
+
target="_blank"
|
|
52
|
+
rel="noopener noreferrer"
|
|
53
|
+
className="card"
|
|
54
|
+
>
|
|
55
|
+
<h2>
|
|
56
|
+
presetUltramodern Guide
|
|
57
|
+
<img
|
|
58
|
+
className="arrow-right"
|
|
59
|
+
src="https://lf3-static.bytednsdoc.com/obj/eden-cn/zq-uylkvT/ljhwZthlaukjlkulzlp/arrow-right.svg"
|
|
60
|
+
alt="Guide"
|
|
61
|
+
/>
|
|
62
|
+
</h2>
|
|
63
|
+
<p>Review the MV-first, TanStack-ready, Effect-ready public preset.</p>
|
|
64
|
+
</a>
|
|
65
|
+
<a
|
|
66
|
+
href="https://modernjs.dev/en/configure/app/usage.html"
|
|
67
|
+
target="_blank"
|
|
68
|
+
className="card"
|
|
69
|
+
rel="noreferrer"
|
|
70
|
+
>
|
|
71
|
+
<h2>
|
|
72
|
+
Configure presetUltramodern
|
|
73
|
+
<img
|
|
74
|
+
className="arrow-right"
|
|
75
|
+
src="https://lf3-static.bytednsdoc.com/obj/eden-cn/zq-uylkvT/ljhwZthlaukjlkulzlp/arrow-right.svg"
|
|
76
|
+
alt="Tutorials"
|
|
77
|
+
/>
|
|
78
|
+
</h2>
|
|
79
|
+
<p>Tune the generated defaults in <code className="code">modern.config.ts</code>.</p>
|
|
80
|
+
</a>
|
|
81
|
+
<a
|
|
82
|
+
href="https://github.com/web-infra-dev/modern.js/blob/main/packages/toolkit/create/template/.github/workflows/ultramodern-gates.yml.handlebars"
|
|
83
|
+
target="_blank"
|
|
84
|
+
className="card"
|
|
85
|
+
rel="noreferrer"
|
|
86
|
+
>
|
|
87
|
+
<h2>
|
|
88
|
+
Ultramodern Gates
|
|
89
|
+
<img
|
|
90
|
+
className="arrow-right"
|
|
91
|
+
src="https://lf3-static.bytednsdoc.com/obj/eden-cn/zq-uylkvT/ljhwZthlaukjlkulzlp/arrow-right.svg"
|
|
92
|
+
alt="Config"
|
|
93
|
+
/>
|
|
94
|
+
</h2>
|
|
95
|
+
<p>The starter includes a PR workflow for <code className="code">ultramodern:check</code> and build.</p>
|
|
96
|
+
</a>
|
|
97
|
+
<a
|
|
98
|
+
href="https://modernjs.dev/en/configure/app/bff/effect.html"
|
|
99
|
+
target="_blank"
|
|
100
|
+
rel="noopener noreferrer"
|
|
101
|
+
className="card"
|
|
102
|
+
>
|
|
103
|
+
<h2>
|
|
104
|
+
BFF + Effect
|
|
105
|
+
<img
|
|
106
|
+
className="arrow-right"
|
|
107
|
+
src="https://lf3-static.bytednsdoc.com/obj/eden-cn/zq-uylkvT/ljhwZthlaukjlkulzlp/arrow-right.svg"
|
|
108
|
+
alt="Github"
|
|
109
|
+
/>
|
|
110
|
+
</h2>
|
|
111
|
+
<p>Keep Effect as the preferred BFF lane while Hono stays an explicit fallback.</p>
|
|
112
|
+
</a>
|
|
113
|
+
</div>
|
|
114
|
+
</main>
|
|
115
|
+
</div>
|
|
116
|
+
);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export default Index;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@modern-js/tsconfig/base",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"declaration": false,
|
|
5
|
+
"jsx": "preserve",
|
|
6
|
+
"baseUrl": "./",
|
|
7
|
+
"paths": {
|
|
8
|
+
"@/*": ["./src/*"],
|
|
9
|
+
"@api/*": ["./api/*"],
|
|
10
|
+
"@shared/*": ["./shared/*"]
|
|
11
|
+
},
|
|
12
|
+
"rootDir": "./src"
|
|
13
|
+
},
|
|
14
|
+
"include": ["src", "api", "shared", "config", "modern.config.ts"],
|
|
15
|
+
"exclude": ["**/node_modules"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# {{packageName}}
|
|
2
|
+
|
|
3
|
+
Generated UltraModern SuperApp workspace.
|
|
4
|
+
|
|
5
|
+
This workspace keeps `presetUltramodern(...)` as the single public Modern.js
|
|
6
|
+
preset surface and scaffolds the canonical Micro Vertical starter topology:
|
|
7
|
+
|
|
8
|
+
- `apps/shell-super-app` owns shell route assembly and remote manifest wiring.
|
|
9
|
+
- `apps/remotes/remote-commerce` owns the commerce vertical remote.
|
|
10
|
+
- `apps/remotes/remote-identity` owns the identity vertical remote.
|
|
11
|
+
- `apps/remotes/remote-design-system` owns the horizontal design-system remote.
|
|
12
|
+
- `services/service-recommendations-effect` owns the Effect BFF service.
|
|
13
|
+
- `packages/shared-*` provide placeholders for cross-workspace contracts.
|
|
14
|
+
|
|
15
|
+
Run the scaffold validator before adding business code:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm ultramodern:check
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The topology and ownership metadata are generated under `topology/`.
|
|
22
|
+
|
|
23
|
+
Package source metadata is generated at
|
|
24
|
+
`.modernjs/ultramodern-package-source.json`. The default strategy keeps Modern.js
|
|
25
|
+
runtime and tooling packages on `workspace:*` for monorepo development. To create
|
|
26
|
+
a workspace that can install those packages outside the monorepo, generate with
|
|
27
|
+
`--ultramodern-package-source install`; generated shared packages still use
|
|
28
|
+
`workspace:*` because they are part of this workspace.
|