sdnext 0.0.2 → 0.0.3
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 +21 -21
- package/dist/utils/build.js +1 -1
- package/dist/utils/dev.js +1 -1
- package/dist/utils/hook.js +3 -1
- package/package.json +1 -1
- package/src/utils/build.ts +1 -1
- package/src/utils/dev.ts +1 -1
- package/src/utils/hook.ts +6 -2
package/README.md
CHANGED
|
@@ -12,19 +12,19 @@
|
|
|
12
12
|
|
|
13
13
|
### 对比表(Next.js 16 App Router vs sdrr)
|
|
14
14
|
|
|
15
|
-
| Next.js 16(App Router)约定
|
|
16
|
-
|
|
|
17
|
-
| `app/` 作为路由根
|
|
18
|
-
| `page.(ts/tsx/js/jsx)`
|
|
19
|
-
| `layout.(ts/tsx/js/jsx)`
|
|
20
|
-
| 路由分组 `(group)`
|
|
21
|
-
| 动态段 `[id]`
|
|
22
|
-
| catch-all `[...slug]`
|
|
23
|
-
| optional catch-all `[[...slug]]` | 同时生成 `/`(index)与 `:slug/*` 两种匹配
|
|
24
|
-
| `error.(ts/tsx/js/jsx)`
|
|
25
|
-
| `not-found.(ts/tsx/js/jsx)`
|
|
26
|
-
| `@slot`(并行路由)
|
|
27
|
-
| `(.)/(..)/(...)`(拦截路由)
|
|
15
|
+
| Next.js 16(App Router)约定 | sdrr 行为(react-router 映射) | 备注 |
|
|
16
|
+
| -------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------ |
|
|
17
|
+
| `app/` 作为路由根 | 扫描当前工作目录下的 `app/` 并生成 `components/Router.tsx` | 在 monorepo 里通常先 `cd` 到应用包根目录再执行 |
|
|
18
|
+
| `page.(ts/tsx/js/jsx)` | 生成 `index: true` 的子路由组件(目录级页面) | 同名文件选择:`.lazy` 优先,其次 `tsx > jsx > ts > js` |
|
|
19
|
+
| `layout.(ts/tsx/js/jsx)` | 生成父 route 的 `Component`(布局组件) | 典型 layout 需要渲染 `<Outlet />` |
|
|
20
|
+
| 路由分组 `(group)` | 生成 `path` 为空的“pathless route” | 不会出现在 URL 中 |
|
|
21
|
+
| 动态段 `[id]` | 映射为 `:id` | 与 Next 的动态段语义对齐 |
|
|
22
|
+
| catch-all `[...slug]` | 映射为 `:slug/*`(内部用两层 route 生成) | `slug` 是第一个段;剩余段在 `params["*"]` |
|
|
23
|
+
| optional catch-all `[[...slug]]` | 同时生成 `/`(index)与 `:slug/*` 两种匹配 | 与 Next 的“可选”语义对齐 |
|
|
24
|
+
| `error.(ts/tsx/js/jsx)` | 映射为 route 的 `ErrorBoundary` | Next 的 `error.js` 是错误边界概念,近似映射 |
|
|
25
|
+
| `not-found.(ts/tsx/js/jsx)` | 生成 `path: "*"` 的兜底子路由 | 用于该布局/段下的 404 兜底 |
|
|
26
|
+
| `@slot`(并行路由) | 不支持,直接抛错 | `react-router` 缺少命名 slot/outlet 的等价能力 |
|
|
27
|
+
| `(.)/(..)/(...)`(拦截路由) | 不支持,直接抛错 | `react-router` 无等价语义 |
|
|
28
28
|
|
|
29
29
|
## 前置要求
|
|
30
30
|
|
|
@@ -182,14 +182,14 @@ sdrr build pnpm dev --watch
|
|
|
182
182
|
同一目录下:
|
|
183
183
|
|
|
184
184
|
- 同时存在 `layout.*` 和 `page.*`
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
- 该目录会生成一个带 `path` 的布局 route
|
|
186
|
+
- `page.*` 会作为该布局的 `index: true` 子路由
|
|
187
|
+
- 子目录路由会作为该布局的 children
|
|
188
188
|
- 只有 `page.*`
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
- 如果该目录下没有子目录路由:会生成一个普通 route
|
|
190
|
+
- 如果该目录下还有子目录路由:会生成一个父 route(`path` 为目录名),并将 `page.*` 作为其 `index: true` 子路由,同时把子目录路由挂到该父 route 的 `children` 下(从而支持如 `/user/a` 这类嵌套路由)
|
|
191
191
|
- 只有 `layout.*`
|
|
192
|
-
|
|
192
|
+
- 会生成一个“无 path 的布局包装层”(pathless route),更适合放在分组目录 `(xxx)` 下用于包裹子路由
|
|
193
193
|
|
|
194
194
|
### 一个更完整的目录示例
|
|
195
195
|
|
|
@@ -293,8 +293,8 @@ export default function App() {
|
|
|
293
293
|
"scripts": {
|
|
294
294
|
"router:gen": "sdrr build",
|
|
295
295
|
"dev": "sdrr build vite dev -w",
|
|
296
|
-
"build": "sdrr build vite build"
|
|
297
|
-
}
|
|
296
|
+
"build": "sdrr build vite build",
|
|
297
|
+
},
|
|
298
298
|
}
|
|
299
299
|
```
|
|
300
300
|
|
package/dist/utils/build.js
CHANGED
package/dist/utils/dev.js
CHANGED
package/dist/utils/hook.js
CHANGED
|
@@ -151,10 +151,12 @@ async function hook(options, { args }) {
|
|
|
151
151
|
choices: [
|
|
152
152
|
"mutation",
|
|
153
153
|
"query",
|
|
154
|
-
"get"
|
|
154
|
+
"get",
|
|
155
|
+
"skip"
|
|
155
156
|
],
|
|
156
157
|
default: type
|
|
157
158
|
});
|
|
159
|
+
if ("skip" === answer) continue;
|
|
158
160
|
const { dir, base } = parse(path);
|
|
159
161
|
await mkdir(join("hooks", dir), {
|
|
160
162
|
recursive: true
|
package/package.json
CHANGED
package/src/utils/build.ts
CHANGED
package/src/utils/dev.ts
CHANGED
|
@@ -16,7 +16,7 @@ export async function dev(options: Record<string, string>, { args }: Command) {
|
|
|
16
16
|
|
|
17
17
|
const child = spawn(process.execPath, [watchPath])
|
|
18
18
|
|
|
19
|
-
const child2 = spawn(args.
|
|
19
|
+
const child2 = spawn(args.join(" "), {
|
|
20
20
|
stdio: "inherit",
|
|
21
21
|
shell: true,
|
|
22
22
|
})
|
package/src/utils/hook.ts
CHANGED
|
@@ -212,12 +212,16 @@ export async function hook(options: Record<string, string>, { args }: Command) {
|
|
|
212
212
|
const oldEntires = entires.filter(([path, { overwrite }]) => !overwrite)
|
|
213
213
|
|
|
214
214
|
for await (const [path, { overwrite, type, ...map }] of newEntires) {
|
|
215
|
-
|
|
215
|
+
type OperationType = HookType | "skip"
|
|
216
|
+
|
|
217
|
+
const answer = await select<OperationType>({
|
|
216
218
|
message: path,
|
|
217
|
-
choices: ["mutation", "query", "get"],
|
|
219
|
+
choices: ["mutation", "query", "get", "skip"],
|
|
218
220
|
default: type,
|
|
219
221
|
})
|
|
220
222
|
|
|
223
|
+
if (answer === "skip") continue
|
|
224
|
+
|
|
221
225
|
const { dir, base } = parse(path)
|
|
222
226
|
await mkdir(join("hooks", dir), { recursive: true })
|
|
223
227
|
await writeFile(
|