@bleedingdev/modern-js-main-doc 3.9.0-ultramodern.5 → 3.9.0-ultramodern.7

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.
@@ -185,7 +185,6 @@ export default defineConfig({
185
185
  endpoint: '/_data/batch',
186
186
  maxBatchSize: 16,
187
187
  maxBatchBytes: 64 * 1024,
188
- flushIntervalMs: 8,
189
188
  maxConcurrency: 4,
190
189
  requestTimeoutMs: 10000,
191
190
  allowedMethods: ['GET'],
@@ -219,9 +218,9 @@ export default defineConfig({
219
218
  });
220
219
  ```
221
220
 
222
- `batch.flushIntervalMs` controls the client-side micro-batch window in the generated Effect client. `maxConcurrency` and `requestTimeoutMs` are applied by the server batch gateway when dispatching items.
221
+ `maxConcurrency` and `requestTimeoutMs` control the server batch gateway. Native `HttpApiClient` calls send individual requests; they do not automatically batch requests.
223
222
 
224
- The generated `api.client.*` API only exists for loader-materialized `@api/index` imports. Directly importing the server entry (`api/index`) exposes the Effect BFF definition; its `client` property is a placeholder that fails on operation access.
223
+ Import a shared `HttpApi` contract and pass it to `HttpApiClient.make` or `makeEffectHttpApiClient`. The client is fully type-inferred; `defineEffectBff` exposes server handlers and does not contain a client.
225
224
 
226
225
  ## Effect cohort
227
226
 
@@ -116,15 +116,20 @@ const layer = HttpApiBuilder.layer(bffApi).pipe(
116
116
  export default defineEffectBff({ api: bffApi, layer });
117
117
  ```
118
118
 
119
- Call Effect endpoints from browser code via `@api/index`:
119
+ Create a native, fully inferred client from the shared contract:
120
120
 
121
121
  ```ts title="src/routes/page.tsx"
122
- import api from '@api/index';
122
+ import { Effect, makeEffectHttpApiClient } from '@modern-js/bff-effect/effect-client';
123
+ import { bffApi } from '../../shared/api';
123
124
 
124
- const response = await api.client.hello.ping({});
125
+ const response = await Effect.runPromise(
126
+ makeEffectHttpApiClient(bffApi, { baseUrl: '/api' }).pipe(
127
+ Effect.flatMap(client => client.hello.ping({})),
128
+ ),
129
+ );
125
130
  ```
126
131
 
127
- The `api.client.*` surface is materialized by the BFF loader for `@api/index` imports. Do not import `api/index` directly and expect `client` to run in server code, scripts, or tests; direct entry imports expose the server runtime definition, and `client` is only a typed placeholder there.
132
+ Requests, responses, and declared errors are inferred from `bffApi`. No client generation or server-entry import is needed.
128
133
 
129
134
  For UltraModern, Effect `HttpApi` plus Effect BFF is the single blessed authored HTTP path. Use `HttpApi` endpoints with `query`, `params`, `payload`, `success`, and declared errors such as `HttpApiSchema.status(...)`; implement them with `HttpApiBuilder.group(...).handle(...)` and `HttpApiBuilder.layer(...).pipe(Layer.provide(...))`, then default-export the entry as `defineEffectBff({ api, layer })`. See `packages/server/bff-effect/tests/effect-edge-runtime.test.ts` for the live runtime shape.
130
135
 
@@ -18,17 +18,9 @@ UltraModern.js 3.0 is our SuperApp framework forked from Modern.js. It keeps the
18
18
  - Add platform-level contracts only where they improve cross-team reliability.
19
19
  - Keep escape hatches explicit and outside the generated HTTP API path.
20
20
 
21
- ## Compatibility Contract
21
+ ## Current Workspace Contract
22
22
 
23
- UltraModern.js 3.0 keeps:
24
-
25
- - Modern.js app/config/plugin mental model.
26
- - Existing project structure and command flow.
27
- - Progressive adoption path (apps can stay mostly unchanged).
28
-
29
- UltraModern.js additions are designed as the default product surface for new SuperApps. The framework direction is Effect + TanStack + SSR + Micro Verticals, and generated HTTP API work uses that direction by default instead of preserving parallel raw-handler layouts.
30
- Existing Modern.js apps can migrate gradually; once an API surface is generated
31
- or migrated as UltraModern HTTP API, it must use the strict Effect HttpApi path.
23
+ UltraModern.js uses Effect HttpApi, TanStack Router, SSR, and independently deployable Micro Verticals. Generated workspaces use `api/index.ts`, `shared/api.ts`, and `src/api/*` with concrete Effect schemas. The CLI creates, adds to, and validates workspaces against the current contract.
32
24
 
33
25
  ## Intentional Differences (v3 line)
34
26
 
@@ -56,21 +48,9 @@ or migrated as UltraModern HTTP API, it must use the strict Effect HttpApi path.
56
48
  - Generated UltraModern API work uses the Effect runtime only; raw Hono/function handlers are not part of the generated API architecture.
57
49
  - We make incompatible scaffold changes when they remove architecture drift.
58
50
 
59
- ## Migration Guide
60
-
61
- For teams already on Modern.js 3.0 or an older BleedingDev UltraModern scaffold, the adoption path is to move API work onto the strict Effect HttpApi surface instead of preserving older raw handler layouts.
62
-
63
- 1. Keep existing Modern.js apps running as-is while they are outside the generated UltraModern surface. TanStack Router is the preferred path for new scaffolds and incremental route adoption, but route migration can happen on the team's schedule.
64
- 2. Use `bff.runtimeFramework: 'effect'` with `bff.effect.strictEffectApproach: true` for API work. Entries live at `api/index.ts`, contracts live at `shared/api.ts`, clients live under `src/api/*`, and request/response/error shapes come from Effect `Schema` plus `HttpApi`.
65
- 3. Treat raw handlers, `api/lambda/**`, manual `Response` construction, and manual request parsing as migration defects in generated or migrated UltraModern workspaces.
66
- 4. The public preset now ships with explicit release and certification gates. Generated workspaces include `.github/workflows/ultramodern-workspace-gates.yml`, so `pnpm check` and `pnpm build` stay part of the local adoption contract from day one while CI runs the primitive gates as parallel matrix jobs.
67
-
68
- For an older generated workspace, migrate by treating the published cohort as
69
- the source of truth:
51
+ ## Create and Validate a Workspace
70
52
 
71
53
  ```bash
72
- pnpm dlx @bleedingdev/modern-js-ultramodern-create@latest --help
73
- pnpm dlx @bleedingdev/modern-js-ultramodern-create@latest catalog --vertical --dry-run
74
54
  pnpm dlx @bleedingdev/modern-js-ultramodern-create@latest catalog --vertical
75
55
  mise install
76
56
  mise exec -- pnpm install
@@ -78,73 +58,12 @@ mise exec -- pnpm check
78
58
  mise exec -- pnpm build
79
59
  ```
80
60
 
81
- ### Migrating localized Cloudflare SSR workspaces
82
-
83
- Current cohorts localize Cloudflare SSR workspaces.
84
- The framework moves bare locale-root redirects into the framework-owned
85
- Cloudflare Worker entry and the i18n server runtime. A request for `/` is
86
- redirected server-side with `302` to the negotiated locale path, for example
87
- `/cs` for `Accept-Language: cs-CZ` or `/en` for English and fallback traffic.
88
-
89
- Existing generated workspaces should upgrade the whole BleedingDev Modern
90
- package cohort together. Resolve the current cohort version first, then run
91
- the matching migration:
92
-
93
- ```bash
94
- COHORT="$(npm view @bleedingdev/modern-js-ultramodern-create version)"
95
- pnpm dlx "@bleedingdev/modern-js-ultramodern-create@$COHORT" ultramodern \
96
- migrate-strict-effect --version "$COHORT"
97
- pnpm install
98
- pnpm check
99
- pnpm build
100
- pnpm cloudflare:build
101
- ```
102
-
103
- For deployed Cloudflare Workers, redeploy after the cohort update and verify
104
- the root response before accepting the migration:
61
+ Localized Cloudflare SSR workspaces redirect `/` on the server to the negotiated locale. For example, `Accept-Language: cs-CZ` returns `302` with `Location: /cs`, `Cache-Control: private, no-store`, and `Vary` covering locale detection headers. Validate the deployed Worker with:
105
62
 
106
63
  ```bash
107
64
  curl -I -H 'Accept-Language: cs-CZ,cs;q=0.9,en;q=0.1' https://<worker-host>/
108
65
  ```
109
66
 
110
- The expected response is `302` with `Location: /cs` or the matching locale,
111
- `Cache-Control: private, no-store`, and `Vary` covering the locale detection
112
- headers. Following the redirect should return the SSR locale page with the
113
- matching document language and i18n SSR data.
114
-
115
- Do not fix older root `404` responses by adding app-owned root route files,
116
- client-side redirects, custom navigation wrappers, Cloudflare Worker
117
- postprocessing, generated output edits, or local redirect shims. If `/` still
118
- returns `404` after upgrading, confirm the production build log shows
119
- `Modern.js Framework v<cohort-version>` for the cohort you migrated to and
120
- redeploy the Worker.
121
-
122
- Strict generated API migration is part of every current cohort: the direct
123
- `api/index.ts` generator, generated `.mts` checks, the strict Oxlint boundary
124
- rule set, Effect cohort overrides, and the strict Effect migration command.
125
- Agents that cannot install the BleedingDev cohort yet should use the local
126
- Modern.js workspace for migration validation; otherwise pin the target cohort
127
- with `--ultramodern-package-version`.
128
-
129
- Before hand-editing package aliases or generated metadata, run the framework
130
- migration command from the target workspace:
131
-
132
- ```bash
133
- COHORT="$(npm view @bleedingdev/modern-js-ultramodern-create version)"
134
- pnpm dlx "@bleedingdev/modern-js-ultramodern-create@$COHORT" ultramodern \
135
- migrate-strict-effect --version "$COHORT"
136
- pnpm api:check
137
- pnpm contract:check
138
- ```
139
-
140
- The command updates `.modernjs/ultramodern.json`, root
141
- `modernjs.packageSource`, generated Modern package aliases, framework-owned
142
- toolchain pins, direct topology API metadata, strict Effect pnpm
143
- overrides/trust policy, and the pnpm lockfile. Remaining failures are source
144
- migration work: move code to `shared/api.ts`, `api/index.ts`, and
145
- `src/api/*-client.ts`, then delete `api/effect`, `api/lambda`, `shared/effect`,
146
- and `src/effect`.
147
-
148
67
  Generated strict Effect workspaces pin the compatible Effect cohort with pnpm
149
68
  overrides: `effect@4.0.0-rc.112`, `@effect/opentelemetry@4.0.0-rc.112`,
150
69
  and `@effect/vitest@4.0.0-rc.112`. Do not add app-local direct Effect
@@ -178,7 +178,6 @@ export default defineConfig({
178
178
  endpoint: '/_data/batch',
179
179
  maxBatchSize: 16,
180
180
  maxBatchBytes: 64 * 1024,
181
- flushIntervalMs: 8,
182
181
  maxConcurrency: 4,
183
182
  requestTimeoutMs: 10000,
184
183
  allowedMethods: ['GET'],
@@ -212,9 +211,9 @@ export default defineConfig({
212
211
  });
213
212
  ```
214
213
 
215
- `batch.flushIntervalMs` 用于控制生成的 Effect 客户端微批处理窗口;`maxConcurrency` 与 `requestTimeoutMs` 由服务端批处理网关用于内部请求分发。
214
+ `maxConcurrency` 与 `requestTimeoutMs` 控制服务端批处理网关。原生 `HttpApiClient` 发送独立请求,不会自动批处理。
216
215
 
217
- 生成的 `api.client.*` API 只存在于 loader 物化后的 `@api/index` 导入中。直接导入服务端入口(`api/index`)时拿到的是 Effect BFF 定义;其中的 `client` 属性只是占位,并会在访问具体操作时报错。
216
+ 导入共享 `HttpApi` 契约并传给 `HttpApiClient.make` `makeEffectHttpApiClient`,即可获得完全类型推导的客户端。`defineEffectBff` 只提供服务端 handler,不包含客户端。
218
217
 
219
218
  ## Effect 版本组
220
219
 
@@ -117,15 +117,20 @@ const layer = HttpApiBuilder.layer(bffApi).pipe(
117
117
  export default defineEffectBff({ api: bffApi, layer });
118
118
  ```
119
119
 
120
- 在浏览器代码中通过 `@api/index` 调用接口:
120
+ 从共享契约创建原生、完全类型推导的客户端:
121
121
 
122
122
  ```ts title="src/routes/page.tsx"
123
- import api from '@api/index';
123
+ import { Effect, makeEffectHttpApiClient } from '@modern-js/bff-effect/effect-client';
124
+ import { bffApi } from '../../shared/api';
124
125
 
125
- const response = await api.client.hello.ping({});
126
+ const response = await Effect.runPromise(
127
+ makeEffectHttpApiClient(bffApi, { baseUrl: '/api' }).pipe(
128
+ Effect.flatMap(client => client.hello.ping({})),
129
+ ),
130
+ );
126
131
  ```
127
132
 
128
- `api.client.*` 由 BFF loader 针对 `@api/index` 导入物化生成。不要直接导入 `api/index` 并期望在服务端代码、脚本或测试中运行 `client`;直接导入入口时拿到的是服务端运行时定义,其中的 `client` 只是类型占位。
133
+ 请求、响应和声明的错误类型均从 `bffApi` 推导,无需生成客户端代码或导入服务端入口。
129
134
 
130
135
  原生 Hono 应用从 `@modern-js/plugin-bff/server` 导入操作符。生成的 UltraModern
131
136
  应用继续使用严格 Effect API。Worker handler 及其请求上下文使用
@@ -16,15 +16,11 @@ UltraModern.js 3.0 是我们从 Modern.js 分叉出来的 SuperApp 框架。它
16
16
  - 仅在跨团队稳定性场景增加平台契约。
17
17
  - 保留显式 escape hatch,但它们必须位于生成 HTTP API 模块之外。
18
18
 
19
- ## 兼容性承诺
19
+ ## 当前 Workspace 契约
20
20
 
21
- UltraModern.js 3.0 保持以下不变:
22
-
23
- - Modern.js 的应用/配置/插件心智模型。
24
- - 既有项目结构与命令使用方式。
25
- - 渐进式接入路径(应用无需大规模重构)。
26
-
27
- UltraModern.js 的增强能力是新 SuperApp 的默认产品面。框架方向是 Effect + TanStack + SSR + Micro Verticals,生成的 HTTP API 只走严格 Effect HttpApi surface。既有 Modern.js 应用可以渐进迁移;一旦某个 API surface 被生成为或迁移为 UltraModern HTTP API,就必须使用严格 Effect HttpApi 路径。
21
+ UltraModern.js 使用 Effect HttpApi、TanStack Router、SSR 和可独立部署的 Micro Verticals。
22
+ 生成的 workspace 使用 `api/index.ts`、`shared/api.ts`、`src/api/*` 和具体的 Effect schema。
23
+ CLI 按当前契约创建、扩展和验证 workspace。
28
24
 
29
25
  ## 有意引入的差异(3.0 线)
30
26
 
@@ -50,20 +46,9 @@ UltraModern.js 的增强能力是新 SuperApp 的默认产品面。框架方向
50
46
  - 生成的 UltraModern HTTP API 只走严格 Effect HttpApi surface;原始 request handler 和 Hono/file-function API 不属于生成架构。
51
47
  - 除非稳定性硬需求,否则避免引入破坏性 API 变更。
52
48
 
53
- ## 迁移指南
54
-
55
- 对于已经在使用 Modern.js 3.0 或旧版 BleedingDev UltraModern scaffold 的团队,迁移路径是把 API 工作迁到严格 Effect HttpApi surface,而不是保留旧的原始 handler 布局。
56
-
57
- 1. 既有 Modern.js 应用在尚未进入生成 UltraModern surface 前可以继续按现状运行。TanStack Router 是新脚手架与增量迁移的优先路径,团队可以按自己的节奏迁移路由层。
58
- 2. 新建或迁移中的 BFF 能力使用 `bff.runtimeFramework: 'effect'`、`bff.effect.entry: './api/index'` 和 `bff.effect.strictEffectApproach: true`。接口先改 `shared/api.ts` 的 `HttpApi` 契约,再在 `api/index.ts` 用 `defineEffectBff(...)` / `HttpApiBuilder` 实现。
59
- 3. 在生成或已迁移的 UltraModern workspace 中,把 raw handler、`api/lambda/**`、手写 `Response` 和手写 request parsing 视为迁移缺陷。
60
- 4. 这套公开预设现在已经附带显式的发布 / 认证 gate。生成 workspace 会自带 `.github/workflows/ultramodern-workspace-gates.yml`,因此 `pnpm check` 与 `pnpm build` 从第一天开始就是本地接入契约的一部分;CI 会以并行矩阵运行这些基础 gate。
61
-
62
- 旧版生成 workspace 迁移时,以已发布的包 cohort 作为事实来源:
49
+ ## 创建并验证 Workspace
63
50
 
64
51
  ```bash
65
- pnpm dlx @bleedingdev/modern-js-ultramodern-create@latest --help
66
- pnpm dlx @bleedingdev/modern-js-ultramodern-create@latest catalog --vertical --dry-run
67
52
  pnpm dlx @bleedingdev/modern-js-ultramodern-create@latest catalog --vertical
68
53
  mise install
69
54
  mise exec -- pnpm install
@@ -71,62 +56,14 @@ mise exec -- pnpm check
71
56
  mise exec -- pnpm build
72
57
  ```
73
58
 
74
- ### 迁移本地化 Cloudflare SSR workspace
75
-
76
- 当前 cohort 均支持本地化 Cloudflare SSR workspace。框架将裸 locale root 重定向移动到框架拥有的 Cloudflare Worker entry 和 i18n
77
- server runtime 中。请求 `/` 时,框架会按语言协商在服务端返回 `302`,例如
78
- `Accept-Language: cs-CZ` 会跳转到 `/cs`,英语或 fallback 流量会跳转到 `/en`。
79
-
80
- 既有生成 workspace 应整体升级同一个 BleedingDev Modern package cohort。
81
- 先解析当前 cohort 版本,再运行同版本迁移命令:
82
-
83
- ```bash
84
- COHORT="$(npm view @bleedingdev/modern-js-ultramodern-create version)"
85
- pnpm dlx "@bleedingdev/modern-js-ultramodern-create@$COHORT" ultramodern \
86
- migrate-strict-effect --version "$COHORT"
87
- pnpm install
88
- pnpm check
89
- pnpm build
90
- pnpm cloudflare:build
91
- ```
92
-
93
- Cloudflare Workers 已部署环境需要在 cohort 更新后重新部署,并在接受迁移前验证 root
94
- 响应:
59
+ 本地化 Cloudflare SSR workspace 在服务端将 `/` 重定向到协商的语言路径。
60
+ `Accept-Language: cs-CZ` 返回 `302`、`Location: /cs`、
61
+ `Cache-Control: private, no-store`,以及覆盖语言检测 Header `Vary`。
95
62
 
96
63
  ```bash
97
64
  curl -I -H 'Accept-Language: cs-CZ,cs;q=0.9,en;q=0.1' https://<worker-host>/
98
65
  ```
99
66
 
100
- 期望响应是 `302`,并带有 `Location: /cs` 或匹配的 locale、
101
- `Cache-Control: private, no-store`,以及覆盖语言检测 Header 的 `Vary`。继续跟随该
102
- redirect 后,应返回匹配语言的 SSR 页面,文档语言和 i18n SSR 数据也应一致。
103
-
104
- 不要通过 app 自有 root route、客户端 redirect、自定义导航 wrapper、Cloudflare Worker
105
- postprocess、生成产物编辑或本地 redirect shim 来修复旧版本的 root `404`。如果升级后
106
- `/` 仍然返回 `404`,先确认生产构建日志显示的
107
- `Modern.js Framework v<cohort-version>` 就是迁移目标 cohort,然后重新部署 Worker。
108
-
109
- 严格生成 API 迁移是当前每个 cohort 的组成部分:直接 `api/index.ts` 生成器、生成的
110
- `.mts` 检查、严格 Oxlint 边界规则、Effect 版本组 overrides 和严格 Effect 迁移命令。
111
- 还不能安装 BleedingDev cohort 的 agent 应使用本地 Modern.js workspace 做迁移校验;
112
- 否则用 `--ultramodern-package-version` 固定目标 cohort。
113
-
114
- 手写 package alias 或生成 metadata 之前,先在目标 workspace 运行框架迁移命令:
115
-
116
- ```bash
117
- COHORT="$(npm view @bleedingdev/modern-js-ultramodern-create version)"
118
- pnpm dlx "@bleedingdev/modern-js-ultramodern-create@$COHORT" ultramodern \
119
- migrate-strict-effect --version "$COHORT"
120
- pnpm api:check
121
- pnpm contract:check
122
- ```
123
-
124
- 该命令会更新 `.modernjs/ultramodern.json`、根 `modernjs.packageSource`、生成的
125
- Modern package alias、框架拥有的 toolchain pin、直接 topology API metadata、严格 Effect
126
- pnpm overrides/trust policy 和 pnpm lockfile。剩余失败就是源码迁移:把代码移到
127
- `shared/api.ts`、`api/index.ts` 和 `src/api/*-client.ts`,再删除 `api/effect`、
128
- `api/lambda`、`shared/effect` 和 `src/effect`。
129
-
130
67
  严格 Effect 生成 workspace 会通过 pnpm overrides 固定兼容版本组:
131
68
  `effect@4.0.0-rc.112`、`@effect/opentelemetry@4.0.0-rc.112` 和
132
69
  `@effect/vitest@4.0.0-rc.112`。不要添加与这些 overrides 冲突的 app 本地直接
package/package.json CHANGED
@@ -19,13 +19,13 @@
19
19
  "modern.js",
20
20
  "ultramodern.js"
21
21
  ],
22
- "version": "3.9.0-ultramodern.5",
22
+ "version": "3.9.0-ultramodern.7",
23
23
  "publishConfig": {
24
24
  "access": "public"
25
25
  },
26
26
  "dependencies": {
27
- "@modern-js/sandpack-react": "npm:@bleedingdev/modern-js-sandpack-react@3.9.0-ultramodern.5",
28
- "@modern-js/ultramodern-sandpack-profile": "npm:@bleedingdev/modern-js-ultramodern-sandpack-profile@3.9.0-ultramodern.5",
27
+ "@modern-js/sandpack-react": "npm:@bleedingdev/modern-js-sandpack-react@3.9.0-ultramodern.7",
28
+ "@modern-js/ultramodern-sandpack-profile": "npm:@bleedingdev/modern-js-ultramodern-sandpack-profile@3.9.0-ultramodern.7",
29
29
  "mermaid": "^11.17.2"
30
30
  },
31
31
  "devDependencies": {