@maiyunnet/kebab 9.3.4 → 9.3.6

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/doc/kebab-rag.md CHANGED
@@ -1360,7 +1360,7 @@ index/variables/VER.md
1360
1360
 
1361
1361
  # Variable: VER
1362
1362
 
1363
- > `const` **VER**: `"9.3.4"` = `'9.3.4'`
1363
+ > `const` **VER**: `"9.3.6"` = `'9.3.6'`
1364
1364
 
1365
1365
  Defined in: [index.ts:10](https://github.com/maiyunnet/kebab/blob/master/index.ts#L10)
1366
1366
 
@@ -3258,7 +3258,7 @@ lib/core/functions/clone.md
3258
3258
 
3259
3259
  > **clone**\<`T`\>(`obj`): `T`
3260
3260
 
3261
- Defined in: [lib/core.ts:1006](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1006)
3261
+ Defined in: [lib/core.ts:1060](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1060)
3262
3262
 
3263
3263
  完整的克隆一份数组/对象
3264
3264
 
@@ -3322,7 +3322,7 @@ lib/core/functions/debug.md
3322
3322
 
3323
3323
  > **debug**(`message?`, ...`optionalParams`): `void`
3324
3324
 
3325
- Defined in: [lib/core.ts:1040](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1040)
3325
+ Defined in: [lib/core.ts:1094](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1094)
3326
3326
 
3327
3327
  打印调试信息,线上环境不会打印
3328
3328
 
@@ -3357,7 +3357,7 @@ lib/core/functions/display.md
3357
3357
 
3358
3358
  > **display**(`message?`, ...`optionalParams`): `void`
3359
3359
 
3360
- Defined in: [lib/core.ts:1053](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1053)
3360
+ Defined in: [lib/core.ts:1107](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1107)
3361
3361
 
3362
3362
  向控制台直接显示内容,一般情况下禁止使用
3363
3363
 
@@ -3462,7 +3462,7 @@ lib/core/functions/getLog.md
3462
3462
 
3463
3463
  > **getLog**(`opt`): `Promise`\<`false` \| `string`[][] \| `null`\>
3464
3464
 
3465
- Defined in: [lib/core.ts:913](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L913)
3465
+ Defined in: [lib/core.ts:967](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L967)
3466
3466
 
3467
3467
  获取日志内容为一个数组
3468
3468
 
@@ -3568,7 +3568,7 @@ lib/core/functions/loadEnv.md
3568
3568
 
3569
3569
  > **loadEnv**(`dir`): `Promise`\<`void`\>
3570
3570
 
3571
- Defined in: [lib/core.ts:1105](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1105)
3571
+ Defined in: [lib/core.ts:1159](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1159)
3572
3572
 
3573
3573
  加载 .env 文件到 process.env,若文件不存在则跳过
3574
3574
 
@@ -3597,7 +3597,7 @@ lib/core/functions/log.md
3597
3597
 
3598
3598
  > **log**(`opt`, `msg`, `fend?`): `void`
3599
3599
 
3600
- Defined in: [lib/core.ts:807](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L807)
3600
+ Defined in: [lib/core.ts:861](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L861)
3601
3601
 
3602
3602
  写入文件日志
3603
3603
 
@@ -3638,7 +3638,7 @@ lib/core/functions/ls.md
3638
3638
 
3639
3639
  > **ls**(`opt`): `Promise`\<`object`[]\>
3640
3640
 
3641
- Defined in: [lib/core.ts:967](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L967)
3641
+ Defined in: [lib/core.ts:1021](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1021)
3642
3642
 
3643
3643
  获取目录内文件/文件夹列表
3644
3644
 
@@ -3964,7 +3964,7 @@ lib/core/functions/removeGlobal.md
3964
3964
 
3965
3965
  > **removeGlobal**(`key`, `hosts?`): `Promise`\<`string`[]\>
3966
3966
 
3967
- Defined in: [lib/core.ts:730](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L730)
3967
+ Defined in: [lib/core.ts:736](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L736)
3968
3968
 
3969
3969
  移除某个跨线程/跨内网服务器全局变量
3970
3970
 
@@ -3999,7 +3999,7 @@ lib/core/functions/resolveEnvVars.md
3999
3999
 
4000
4000
  > **resolveEnvVars**(`obj`): `void`
4001
4001
 
4002
- Defined in: [lib/core.ts:1135](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1135)
4002
+ Defined in: [lib/core.ts:1189](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1189)
4003
4003
 
4004
4004
  将配置对象中的 ${ENV_VAR} 占位符替换为 process.env 的值
4005
4005
 
@@ -4028,7 +4028,7 @@ lib/core/functions/sendNpm.md
4028
4028
 
4029
4029
  > **sendNpm**(`path`, `hosts?`): `Promise`\<`string`[]\>
4030
4030
 
4031
- Defined in: [lib/core.ts:646](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L646)
4031
+ Defined in: [lib/core.ts:649](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L649)
4032
4032
 
4033
4033
  向本机或局域网 RPC 发送 npm install 操作
4034
4034
 
@@ -4091,6 +4091,53 @@ PM2 操作类型
4091
4091
 
4092
4092
  `Promise`\<`string`[]\>
4093
4093
 
4094
+ lib/core/functions/sendProject.md
4095
+ ---
4096
+
4097
+ [**Documents for @maiyunnet/kebab**](../../../index.md)
4098
+
4099
+ ***
4100
+
4101
+ [Documents for @maiyunnet/kebab](../../../index.md) / [lib/core](../index.md) / sendProject
4102
+
4103
+ # Function: sendProject()
4104
+
4105
+ > **sendProject**(`path`, `key`, `value`, `hosts?`): `Promise`\<`string`[]\>
4106
+
4107
+ Defined in: [lib/core.ts:805](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L805)
4108
+
4109
+ 向本机或局域网 RPC 发送项目配置更新操作
4110
+
4111
+ ## Parameters
4112
+
4113
+ ### path
4114
+
4115
+ `string`
4116
+
4117
+ 项目路径,相对 Kebab 根
4118
+
4119
+ ### key
4120
+
4121
+ `string`
4122
+
4123
+ 要更新的键名(目前仅支持 staticVer)
4124
+
4125
+ ### value
4126
+
4127
+ `string`
4128
+
4129
+ 要更新的值
4130
+
4131
+ ### hosts?
4132
+
4133
+ `string`[] \| `"config"`
4134
+
4135
+ 局域网列表
4136
+
4137
+ ## Returns
4138
+
4139
+ `Promise`\<`string`[]\>
4140
+
4094
4141
  lib/core/functions/sendReload.md
4095
4142
  ---
4096
4143
 
@@ -4207,7 +4254,7 @@ lib/core/functions/setGlobal.md
4207
4254
 
4208
4255
  > **setGlobal**(`key`, `data`, `hosts?`): `Promise`\<`string`[]\>
4209
4256
 
4210
- Defined in: [lib/core.ts:689](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L689)
4257
+ Defined in: [lib/core.ts:695](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L695)
4211
4258
 
4212
4259
  设置跨线程/指定的局域网主机的全局变量
4213
4260
 
@@ -4306,7 +4353,7 @@ lib/core/functions/updateCode.md
4306
4353
 
4307
4354
  > **updateCode**(`sourcePath`, `path`, `hosts?`, `config?`, `strict?`): `Promise`\<`Record`\<`string`, \{ `result`: `boolean`; `return`: `string`; \}\>\>
4308
4355
 
4309
- Defined in: [lib/core.ts:742](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L742)
4356
+ Defined in: [lib/core.ts:748](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L748)
4310
4357
 
4311
4358
  上传并覆盖代码文件,config.json、kebab.json、.js.map、.ts, .gitignore 不会被覆盖和新创建
4312
4359
 
@@ -4359,7 +4406,7 @@ lib/core/functions/writeEventStreamHead.md
4359
4406
 
4360
4407
  > **writeEventStreamHead**(`res`): `void`
4361
4408
 
4362
- Defined in: [lib/core.ts:1075](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1075)
4409
+ Defined in: [lib/core.ts:1129](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1129)
4363
4410
 
4364
4411
  ## Parameters
4365
4412
 
@@ -4384,7 +4431,7 @@ lib/core/functions/writeHead.md
4384
4431
 
4385
4432
  > **writeHead**(`res`, `statusCode`, `headers?`): `void`
4386
4433
 
4387
- Defined in: [lib/core.ts:1064](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1064)
4434
+ Defined in: [lib/core.ts:1118](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1118)
4388
4435
 
4389
4436
  让 res 发送头部(前提是头部没有被发送才能调用本方法
4390
4437
 
@@ -4425,7 +4472,7 @@ lib/core/functions/write.md
4425
4472
 
4426
4473
  > **write**(`res`, `data`): `void`
4427
4474
 
4428
- Defined in: [lib/core.ts:1087](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1087)
4475
+ Defined in: [lib/core.ts:1141](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1141)
4429
4476
 
4430
4477
  向 res 发送数据
4431
4478
 
@@ -4509,6 +4556,7 @@ lib/core/index.md
4509
4556
  - [resolveEnvVars](functions/resolveEnvVars.md)
4510
4557
  - [sendNpm](functions/sendNpm.md)
4511
4558
  - [sendPm2](functions/sendPm2.md)
4559
+ - [sendProject](functions/sendProject.md)
4512
4560
  - [sendReload](functions/sendReload.md)
4513
4561
  - [sendRestart](functions/sendRestart.md)
4514
4562
  - [setCookie](functions/setCookie.md)
@@ -4594,7 +4642,7 @@ lib/core/interfaces/ILogOptions.md
4594
4642
 
4595
4643
  # Interface: ILogOptions
4596
4644
 
4597
- Defined in: [lib/core.ts:790](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L790)
4645
+ Defined in: [lib/core.ts:844](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L844)
4598
4646
 
4599
4647
  log 设置的选项
4600
4648
 
@@ -4604,7 +4652,7 @@ log 设置的选项
4604
4652
 
4605
4653
  > `optional` **cookie?**: `Record`\<`string`, `string`\>
4606
4654
 
4607
- Defined in: [lib/core.ts:796](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L796)
4655
+ Defined in: [lib/core.ts:850](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L850)
4608
4656
 
4609
4657
  ***
4610
4658
 
@@ -4612,7 +4660,7 @@ Defined in: [lib/core.ts:796](https://github.com/maiyunnet/kebab/blob/master/lib
4612
4660
 
4613
4661
  > `optional` **get?**: `Record`\<`string`, `any`\>
4614
4662
 
4615
- Defined in: [lib/core.ts:795](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L795)
4663
+ Defined in: [lib/core.ts:849](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L849)
4616
4664
 
4617
4665
  ***
4618
4666
 
@@ -4620,7 +4668,7 @@ Defined in: [lib/core.ts:795](https://github.com/maiyunnet/kebab/blob/master/lib
4620
4668
 
4621
4669
  > `optional` **headers?**: `IncomingHttpHeaders`
4622
4670
 
4623
- Defined in: [lib/core.ts:798](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L798)
4671
+ Defined in: [lib/core.ts:852](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L852)
4624
4672
 
4625
4673
  ***
4626
4674
 
@@ -4628,7 +4676,7 @@ Defined in: [lib/core.ts:798](https://github.com/maiyunnet/kebab/blob/master/lib
4628
4676
 
4629
4677
  > `optional` **hostname?**: `string`
4630
4678
 
4631
- Defined in: [lib/core.ts:793](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L793)
4679
+ Defined in: [lib/core.ts:847](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L847)
4632
4680
 
4633
4681
  ***
4634
4682
 
@@ -4636,7 +4684,7 @@ Defined in: [lib/core.ts:793](https://github.com/maiyunnet/kebab/blob/master/lib
4636
4684
 
4637
4685
  > `optional` **path?**: `string`
4638
4686
 
4639
- Defined in: [lib/core.ts:791](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L791)
4687
+ Defined in: [lib/core.ts:845](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L845)
4640
4688
 
4641
4689
  ***
4642
4690
 
@@ -4644,7 +4692,7 @@ Defined in: [lib/core.ts:791](https://github.com/maiyunnet/kebab/blob/master/lib
4644
4692
 
4645
4693
  > `optional` **req?**: `IncomingMessage` \| `Http2ServerRequest` \| `null`
4646
4694
 
4647
- Defined in: [lib/core.ts:794](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L794)
4695
+ Defined in: [lib/core.ts:848](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L848)
4648
4696
 
4649
4697
  ***
4650
4698
 
@@ -4652,7 +4700,7 @@ Defined in: [lib/core.ts:794](https://github.com/maiyunnet/kebab/blob/master/lib
4652
4700
 
4653
4701
  > `optional` **session?**: `Record`\<`string`, `any`\>
4654
4702
 
4655
- Defined in: [lib/core.ts:797](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L797)
4703
+ Defined in: [lib/core.ts:851](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L851)
4656
4704
 
4657
4705
  ***
4658
4706
 
@@ -4660,7 +4708,7 @@ Defined in: [lib/core.ts:797](https://github.com/maiyunnet/kebab/blob/master/lib
4660
4708
 
4661
4709
  > `optional` **urlFull?**: `string`
4662
4710
 
4663
- Defined in: [lib/core.ts:792](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L792)
4711
+ Defined in: [lib/core.ts:846](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L846)
4664
4712
 
4665
4713
  lib/core/type-aliases/TPm2Action.md
4666
4714
  ---
@@ -4749,7 +4797,7 @@ lib/core/variables/global.md
4749
4797
 
4750
4798
  > `const` **global**: `Record`\<`string`, `any`\> = `{}`
4751
4799
 
4752
- Defined in: [lib/core.ts:681](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L681)
4800
+ Defined in: [lib/core.ts:687](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L687)
4753
4801
 
4754
4802
  跨进程全局变量
4755
4803
 
@@ -15745,7 +15793,7 @@ lib/text/functions/getFileExt.md
15745
15793
 
15746
15794
  > **getFileExt**(`path`): `string`
15747
15795
 
15748
- Defined in: [lib/text.ts:527](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L527)
15796
+ Defined in: [lib/text.ts:533](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L533)
15749
15797
 
15750
15798
  获取文件后缀
15751
15799
 
@@ -15774,7 +15822,7 @@ lib/text/functions/getFileNameExt.md
15774
15822
 
15775
15823
  > **getFileNameExt**(`path`): `object`
15776
15824
 
15777
- Defined in: [lib/text.ts:540](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L540)
15825
+ Defined in: [lib/text.ts:546](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L546)
15778
15826
 
15779
15827
  获取文件名和后缀
15780
15828
 
@@ -15811,7 +15859,7 @@ lib/text/functions/getFilename.md
15811
15859
 
15812
15860
  > **getFilename**(`path`, `ext?`): `string`
15813
15861
 
15814
- Defined in: [lib/text.ts:507](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L507)
15862
+ Defined in: [lib/text.ts:513](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L513)
15815
15863
 
15816
15864
  获取文件名
15817
15865
 
@@ -15846,7 +15894,7 @@ lib/text/functions/htmlescape.md
15846
15894
 
15847
15895
  > **htmlescape**(`html`): `string`
15848
15896
 
15849
- Defined in: [lib/text.ts:482](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L482)
15897
+ Defined in: [lib/text.ts:488](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L488)
15850
15898
 
15851
15899
  HTML 特殊字符转换为实体字符
15852
15900
 
@@ -15875,7 +15923,7 @@ lib/text/functions/int2str.md
15875
15923
 
15876
15924
  > **int2str**(`int`, `digits?`, `decimal?`): `string`
15877
15925
 
15878
- Defined in: [lib/text.ts:740](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L740)
15926
+ Defined in: [lib/text.ts:746](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L746)
15879
15927
 
15880
15928
  为解决精度问题,将整数转换为小数字符串
15881
15929
  以下几个示例都是当 digits 为 3、decimal 为 2 时
@@ -16008,7 +16056,7 @@ lib/text/functions/isFalsy.md
16008
16056
 
16009
16057
  > **isFalsy**(`val`): `val is TFalsy`
16010
16058
 
16011
- Defined in: [lib/text.ts:691](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L691)
16059
+ Defined in: [lib/text.ts:697](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L697)
16012
16060
 
16013
16061
  判断一个值是否是虚假的(为 null/undefined/空字符串/false/0)
16014
16062
 
@@ -16149,7 +16197,7 @@ lib/text/functions/isRealPath.md
16149
16197
 
16150
16198
  > **isRealPath**(`path`): `boolean`
16151
16199
 
16152
- Defined in: [lib/text.ts:494](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L494)
16200
+ Defined in: [lib/text.ts:500](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L500)
16153
16201
 
16154
16202
  判断是否是绝对路径,是返回 true,相对路径返回 false
16155
16203
 
@@ -16178,7 +16226,7 @@ lib/text/functions/isTruthy.md
16178
16226
 
16179
16227
  > **isTruthy**\<`T`\>(`val`): `val is Exclude<T, TFalsy>`
16180
16228
 
16181
- Defined in: [lib/text.ts:699](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L699)
16229
+ Defined in: [lib/text.ts:705](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L705)
16182
16230
 
16183
16231
  判断一个值是否是真实的(不为 null/undefined/空字符串/false/0)
16184
16232
 
@@ -16213,7 +16261,7 @@ lib/text/functions/logicalOr.md
16213
16261
 
16214
16262
  > **logicalOr**\<`T`, `T2`\>(`v1`, `v2`): `T` *extends* [`TFalsy`](../type-aliases/TFalsy.md) ? `T2` : `T`
16215
16263
 
16216
- Defined in: [lib/text.ts:708](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L708)
16264
+ Defined in: [lib/text.ts:714](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L714)
16217
16265
 
16218
16266
  类似 || 运算符的效果
16219
16267
 
@@ -16398,7 +16446,7 @@ lib/text/functions/parseJson.md
16398
16446
 
16399
16447
  > **parseJson**\<`T`\>(`str`): `false` \| `T`
16400
16448
 
16401
- Defined in: [lib/text.ts:602](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L602)
16449
+ Defined in: [lib/text.ts:608](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L608)
16402
16450
 
16403
16451
  将字符串解析为对象,返回 false 代表解析失败,支持 BigInt
16404
16452
 
@@ -16597,7 +16645,7 @@ lib/text/functions/str2int.md
16597
16645
 
16598
16646
  > **str2int**(`str`, `digits?`): `number`
16599
16647
 
16600
- Defined in: [lib/text.ts:722](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L722)
16648
+ Defined in: [lib/text.ts:728](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L728)
16601
16649
 
16602
16650
  为解决精度问题,将字符串数字转换为整数显示
16603
16651
  以下几个示例都是当 digits 为 2 时
@@ -16637,7 +16685,7 @@ lib/text/functions/stringifyBuffer.md
16637
16685
 
16638
16686
  > **stringifyBuffer**(`buf`): `string`
16639
16687
 
16640
- Defined in: [lib/text.ts:645](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L645)
16688
+ Defined in: [lib/text.ts:651](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L651)
16641
16689
 
16642
16690
  输出文本格式的 buffer
16643
16691
 
@@ -16666,7 +16714,7 @@ lib/text/functions/stringifyJson.md
16666
16714
 
16667
16715
  > **stringifyJson**(`obj`, `space?`): `string`
16668
16716
 
16669
- Defined in: [lib/text.ts:632](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L632)
16717
+ Defined in: [lib/text.ts:638](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L638)
16670
16718
 
16671
16719
  将对象转换为 json 字符串,返回 false 代表解析失败,支持 BigInt
16672
16720
 
@@ -16701,7 +16749,7 @@ lib/text/functions/stringifyResult.md
16701
16749
 
16702
16750
  > **stringifyResult**(`rtn`): `string`
16703
16751
 
16704
- Defined in: [lib/text.ts:562](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L562)
16752
+ Defined in: [lib/text.ts:568](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L568)
16705
16753
 
16706
16754
  将普通的返回 JSON 对象序列化为字符串
16707
16755
 
@@ -16730,7 +16778,7 @@ lib/text/functions/trimJson.md
16730
16778
 
16731
16779
  > **trimJson**(`json`): `any`
16732
16780
 
16733
- Defined in: [lib/text.ts:653](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L653)
16781
+ Defined in: [lib/text.ts:659](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L659)
16734
16782
 
16735
16783
  递归删除 json 中的字符串首尾空格,会返回一个新的对象
16736
16784
 
@@ -16930,7 +16978,7 @@ lib/text/type-aliases/TFalsy.md
16930
16978
 
16931
16979
  > **TFalsy** = `false` \| `""` \| `0` \| `null` \| `undefined` \| *typeof* `NaN`
16932
16980
 
16933
- Defined in: [lib/text.ts:685](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L685)
16981
+ Defined in: [lib/text.ts:691](https://github.com/maiyunnet/kebab/blob/master/lib/text.ts#L691)
16934
16982
 
16935
16983
  虚假值类型
16936
16984
 
package/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * --- 本文件用来定义每个目录实体地址的常量 ---
6
6
  */
7
7
  /** --- 当前系统版本号 --- */
8
- export declare const VER = "9.3.4";
8
+ export declare const VER = "9.3.6";
9
9
  /** --- 框架根目录,以 / 结尾 --- */
10
10
  export declare const ROOT_PATH: string;
11
11
  /** --- 框架的 LIB,以 / 结尾 --- */
package/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * --- 本文件用来定义每个目录实体地址的常量 ---
7
7
  */
8
8
  /** --- 当前系统版本号 --- */
9
- export const VER = '9.3.4';
9
+ export const VER = '9.3.6';
10
10
  // --- 服务端用的路径 ---
11
11
  const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
12
12
  /** --- /xxx/xxx --- */
package/lib/core.d.ts CHANGED
@@ -210,6 +210,14 @@ export declare function updateCode(sourcePath: string, path: string, hosts?: str
210
210
  'result': boolean;
211
211
  'return': string;
212
212
  }>>;
213
+ /**
214
+ * --- 向本机或局域网 RPC 发送项目配置更新操作 ---
215
+ * @param path 项目路径,相对 Kebab 根
216
+ * @param key 要更新的键名(目前仅支持 staticVer)
217
+ * @param value 要更新的值
218
+ * @param hosts 局域网列表
219
+ */
220
+ export declare function sendProject(path: string, key: string, value: string, hosts?: string[] | 'config'): Promise<string[]>;
213
221
  /** --- log 设置的选项 --- */
214
222
  export interface ILogOptions {
215
223
  'path'?: string;
package/lib/core.js CHANGED
@@ -532,7 +532,10 @@ export async function sendPm2(name, action = 'restart', hosts) {
532
532
  if (hosts === 'config') {
533
533
  hosts = globalConfig.hosts;
534
534
  }
535
- hosts ??= ['127.0.0.1'];
535
+ // --- 未传或 config 展开后为空数组,均回退到本机 ---
536
+ if (!hosts?.length) {
537
+ hosts = ['127.0.0.1'];
538
+ }
536
539
  // --- 局域网模式 ---
537
540
  const time = lTime.stamp();
538
541
  /** --- 返回成功的 host --- */
@@ -569,7 +572,10 @@ export async function sendNpm(path, hosts) {
569
572
  if (hosts === 'config') {
570
573
  hosts = globalConfig.hosts;
571
574
  }
572
- hosts ??= ['127.0.0.1'];
575
+ // --- 未传或 config 展开后为空数组,均回退到本机 ---
576
+ if (!hosts?.length) {
577
+ hosts = ['127.0.0.1'];
578
+ }
573
579
  // --- 局域网模式 ---
574
580
  const time = lTime.stamp();
575
581
  /** --- 返回成功的 host --- */
@@ -659,7 +665,10 @@ export async function updateCode(sourcePath, path, hosts, config = true, strict
659
665
  if (hosts === 'config') {
660
666
  hosts = globalConfig.hosts;
661
667
  }
662
- hosts ??= ['127.0.0.1'];
668
+ // --- 未传或 config 展开后为空数组,均回退到本机 ---
669
+ if (!hosts?.length) {
670
+ hosts = ['127.0.0.1'];
671
+ }
663
672
  /** --- 返回成功的 host --- */
664
673
  const rtn = {};
665
674
  for (const host of hosts) {
@@ -692,6 +701,48 @@ export async function updateCode(sourcePath, path, hosts, config = true, strict
692
701
  }
693
702
  return rtn;
694
703
  }
704
+ /**
705
+ * --- 向本机或局域网 RPC 发送项目配置更新操作 ---
706
+ * @param path 项目路径,相对 Kebab 根
707
+ * @param key 要更新的键名(目前仅支持 staticVer)
708
+ * @param value 要更新的值
709
+ * @param hosts 局域网列表
710
+ */
711
+ export async function sendProject(path, key, value, hosts) {
712
+ if (hosts === 'config') {
713
+ hosts = globalConfig.hosts;
714
+ }
715
+ // --- 未传或 config 展开后为空数组,均回退到本机 ---
716
+ if (!hosts?.length) {
717
+ hosts = ['127.0.0.1'];
718
+ }
719
+ // --- 局域网模式 ---
720
+ const time = lTime.stamp();
721
+ /** --- 返回成功的 host --- */
722
+ const rtn = [];
723
+ for (const host of hosts) {
724
+ const res = await lUndici.get('http://' + host + ':' + globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
725
+ 'action': 'project',
726
+ 'time': time,
727
+ 'path': path,
728
+ [key]: value
729
+ }), globalConfig.rpcSecret), {
730
+ 'timeout': 2
731
+ });
732
+ const content = await res.getContent();
733
+ if (!content) {
734
+ continue;
735
+ }
736
+ const str = content.toString();
737
+ if (str === 'Done') {
738
+ rtn.push(host);
739
+ }
740
+ else {
741
+ debug('[CORE][sendProject] rpc server content error:', str);
742
+ }
743
+ }
744
+ return rtn;
745
+ }
695
746
  /**
696
747
  * --- 写入文件日志 ---
697
748
  * @param opt 选项
package/lib/text.js CHANGED
@@ -393,7 +393,13 @@ export function queryParse(query) {
393
393
  continue;
394
394
  }
395
395
  const pos = i.indexOf('=');
396
- const key = decodeURIComponent(pos === -1 ? i : i.slice(0, pos));
396
+ let key;
397
+ try {
398
+ key = decodeURIComponent(pos === -1 ? i : i.slice(0, pos));
399
+ }
400
+ catch {
401
+ key = pos === -1 ? i : i.slice(0, pos);
402
+ }
397
403
  let value = '';
398
404
  try {
399
405
  value = pos === -1 ? '' : decodeURIComponent(i.slice(pos + 1));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maiyunnet/kebab",
3
- "version": "9.3.4",
3
+ "version": "9.3.6",
4
4
  "description": "Simple, easy-to-use, and fully-featured Node.js framework that is ready-to-use out of the box.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -22,8 +22,8 @@
22
22
  "#kebab/*": "./*"
23
23
  },
24
24
  "dependencies": {
25
- "@aws-sdk/client-s3": "^3.1034.0",
26
- "@aws-sdk/lib-storage": "^3.1034.0",
25
+ "@aws-sdk/client-s3": "^3.1045.0",
26
+ "@aws-sdk/lib-storage": "^3.1045.0",
27
27
  "@litert/http-client": "^1.1.2",
28
28
  "@litert/mime": "^0.1.3",
29
29
  "@litert/redis": "^3.2.1",
@@ -32,33 +32,33 @@
32
32
  "@radix-ui/react-label": "^2.1.8",
33
33
  "@radix-ui/react-slot": "^1.2.4",
34
34
  "@radix-ui/react-switch": "^1.2.6",
35
- "@tailwindcss/cli": "^4.2.4",
35
+ "@tailwindcss/cli": "^4.3.0",
36
36
  "@types/ssh2": "^1.15.5",
37
- "@zilliz/milvus2-sdk-node": "^2.6.13",
38
- "ajv": "^8.18.0",
37
+ "@zilliz/milvus2-sdk-node": "^3.0.0",
38
+ "ajv": "^8.20.0",
39
39
  "ajv-formats": "^3.0.1",
40
40
  "class-variance-authority": "^0.7.1",
41
41
  "clsx": "^2.1.1",
42
42
  "ejs": "^5.0.2",
43
43
  "esbuild": "^0.28.0",
44
44
  "jszip": "^3.10.1",
45
- "mysql2": "^3.22.2",
45
+ "mysql2": "^3.22.3",
46
46
  "node-cron": "^4.2.1",
47
- "openai": "^6.34.0",
47
+ "openai": "^6.37.0",
48
48
  "pg": "^8.20.0",
49
- "react": "^19.2.5",
50
- "react-dom": "^19.2.5",
51
- "react-router-dom": "^7.14.2",
49
+ "react": "^19.2.6",
50
+ "react-dom": "^19.2.6",
51
+ "react-router-dom": "^7.15.0",
52
52
  "ssh2": "^1.17.0",
53
53
  "svg-captcha": "^1.4.0",
54
54
  "tailwind-merge": "^3.5.0",
55
- "tencentcloud-sdk-nodejs": "^4.1.219",
56
- "undici": "^8.1.0"
55
+ "tencentcloud-sdk-nodejs": "^4.1.227",
56
+ "undici": "^8.2.0"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@litert/eslint-plugin-rules": "^0.3.1",
60
60
  "@types/ejs": "^3.1.5",
61
- "@types/node": "^25.6.0",
61
+ "@types/node": "^25.6.2",
62
62
  "@types/pg": "^8.20.0",
63
63
  "@types/react": "^19.2.14",
64
64
  "@types/react-dom": "^19.2.3",
package/sys/master.js CHANGED
@@ -195,6 +195,63 @@ function createRpcListener() {
195
195
  }
196
196
  break;
197
197
  }
198
+ case 'project': {
199
+ // --- 更新项目 kebab.json ---
200
+ if (!msg.path || typeof msg.path !== 'string') {
201
+ res.end('Invalid path');
202
+ return;
203
+ }
204
+ // --- 参数校验前置,避免无效 IO ---
205
+ if (!msg.staticVer || typeof msg.staticVer !== 'string') {
206
+ res.end('Invalid staticVer');
207
+ return;
208
+ }
209
+ let path = msg.path;
210
+ if (path.startsWith('/')) {
211
+ path = path.slice(1);
212
+ }
213
+ if (path.endsWith('/')) {
214
+ path = path.slice(0, -1);
215
+ }
216
+ // --- 拒绝路径穿越,防止跳出 ROOT_CWD ---
217
+ if (path.includes('..')) {
218
+ res.end('Invalid path');
219
+ return;
220
+ }
221
+ /** --- 最终的项目根目录,以 / 结尾,但用户传入的无所谓 --- */
222
+ let to = kebab.ROOT_CWD + path;
223
+ if (!to.endsWith('/')) {
224
+ to += '/';
225
+ }
226
+ if (!await lFs.isDir(to)) {
227
+ res.end('Path not found: ' + to);
228
+ return;
229
+ }
230
+ const projectFile = to + 'kebab.json';
231
+ if (!await lFs.isFile(projectFile)) {
232
+ res.end('kebab.json not found in project path');
233
+ return;
234
+ }
235
+ const projectContent = await lFs.getContent(projectFile, 'utf8');
236
+ if (!projectContent) {
237
+ res.end('Failed to read kebab.json');
238
+ return;
239
+ }
240
+ const projectJson = lText.parseJson(projectContent);
241
+ if (!projectJson) {
242
+ res.end('Invalid kebab.json');
243
+ return;
244
+ }
245
+ // --- 只允许更新 set.staticVer 字段 ---
246
+ projectJson.set ??= {};
247
+ projectJson.set.staticVer = msg.staticVer;
248
+ const wrtn = await lFs.putContent(projectFile, lText.stringifyJson(projectJson, 4));
249
+ if (!wrtn) {
250
+ res.end('Failed to write kebab.json');
251
+ return;
252
+ }
253
+ break;
254
+ }
198
255
  case 'code': {
199
256
  // --- 更新 code 代码包 ---
200
257
  const rtn = await sRoute.getFormData(req);
@@ -221,9 +278,12 @@ function createRpcListener() {
221
278
  to += '/';
222
279
  }
223
280
  if (!await lFs.isDir(to)) {
224
- res.end('Path not found: ' + to);
225
- await sRoute.unlinkUploadFiles(rtn.files);
226
- return;
281
+ if (rtn.post['strict'] === '1') {
282
+ res.end('Path not found: ' + to);
283
+ await sRoute.unlinkUploadFiles(rtn.files);
284
+ return;
285
+ }
286
+ await lFs.mkdir(to);
227
287
  }
228
288
  const buf = await lFs.getContent(file.path);
229
289
  if (!buf) {
@@ -300,20 +360,23 @@ function createRpcListener() {
300
360
  // --- 规则 2:kebab 子项目目录中,仅允许部署 ctr/data/stc/view/lib 子文件夹内的内容 ---
301
361
  // --- 快速跳过:zip 中没有 kebab.json 时整个规则无需执行 ---
302
362
  if (kebabProjectDirs.size > 0) {
303
- // --- 找最长(最精确)匹配的 kebab 项目目录,避免父子项目互相干扰 ---
304
- /** --- 当前文件所属的 kebab 子项目目录,例如 pat 为 "www/pika/ctr/" 时值为 "www/pika/";无匹配则为 null --- */
305
- let longestMatch = null;
363
+ // --- 找最浅(最外层)匹配的 kebab 项目目录 ---
364
+ // --- 以最浅匹配为准,确保根层 kebab 规则优先于嵌套项目 ---
365
+ // --- 例如 backup/ 自身也有 kebab.json,longestMatch 会选 backup/,使其根文件通过 ---
366
+ // --- 改用 shortestMatch 则选根 "",backup 的第一段不在白名单中,正确排除 ---
367
+ /** --- 当前文件所属的最浅 kebab 子项目目录;无匹配则为 null --- */
368
+ let shortestMatch = null;
306
369
  for (const kdir of kebabProjectDirs) {
307
- /** --- 当前 kdir 是否比已有的 longestMatch 更精确(路径更深)--- */
308
- const isDeeper = longestMatch === null || kdir.length > longestMatch.length;
309
- if (pat.startsWith(kdir) && isDeeper) {
310
- longestMatch = kdir;
370
+ /** --- 当前 kdir 是否比已有的 shortestMatch 更浅(路径更短)--- */
371
+ const isShallower = shortestMatch === null || kdir.length < shortestMatch.length;
372
+ if (pat.startsWith(kdir) && isShallower) {
373
+ shortestMatch = kdir;
311
374
  }
312
375
  }
313
- if (longestMatch !== null) {
376
+ if (shortestMatch !== null) {
314
377
  // --- 取相对于 kebab 项目目录的路径,检查第一级子目录 ---
315
- /** --- 相对路径,例如若 pat 为 "www/pika/ctr/" 且 longestMatch 为 "www/pika/",则 relPath 为 "ctr/" --- */
316
- const relPath = pat.slice(longestMatch.length);
378
+ /** --- 相对路径,例如若 pat 为 "www/pika/ctr/" 且 shortestMatch 为 "www/pika/",则 relPath 为 "ctr/" --- */
379
+ const relPath = pat.slice(shortestMatch.length);
317
380
  if (relPath) {
318
381
  /** --- 路径的第一级子目录名,例如 "ctr" 或 "data",用于判断是否在允许列表中 --- */
319
382
  const firstSeg = relPath.split('/')[0];
@@ -19,9 +19,9 @@
19
19
  * 如需打包为 .bundle.js,执行:node ./source/main build
20
20
  *
21
21
  * 【Tailwind CSS 构建】
22
- * bundle 模式下不再加载 CDN,需提前构建 CSS 产物。
23
- * 执行 node ./source/main build 时会自动构建同名 .css,无需单独执行。
24
- * 框架通过 _urlStc _staticVer 自动拼接正确的带版本号 URL。
22
+ * 需提前执行 node ./source/main build -d source/www/example/stc 生成 CSS 产物。
23
+ * 框架通过 _staticPath _staticVer 自动拼接带版本号 URL;
24
+ * import map、props JSON、水合脚本均由框架自动注入 HTML,组件无需手动处理。
25
25
  */
26
26
  interface IUser {
27
27
  'id': string;
@@ -42,17 +42,11 @@ interface IProps {
42
42
  '_staticVer': string;
43
43
  /** --- 框架注入:BrowserRouter 的 basename,如 /test/react-router-page --- */
44
44
  '_routerBase'?: string;
45
- /** --- 框架注入:import map JSON 字符串 --- */
46
- '_importMapJson'?: string;
47
- /** --- 框架注入:水合脚本 --- */
48
- '_hydrateScript'?: string;
49
- /** --- 框架注入:fullProps 序列化 JSON --- */
50
- '_propsJson'?: string;
51
45
  }
52
46
  /**
53
47
  * --- Kebab React BrowserRouter 全页面演示 ---
54
48
  * 框架负责用 StaticRouter(服务端)/ BrowserRouter(客户端)包裹本组件,
55
49
  * 组件内部只需使用 Routes/Route/Link 等,无需自行包裹 Router。
56
50
  */
57
- export default function ReactRouterPage({ title, serverTime, node, users, user, _urlBase, _urlStc, _staticVer, _importMapJson, _hydrateScript, _propsJson, }: IProps): import("react/jsx-runtime").JSX.Element;
51
+ export default function ReactRouterPage({ title, serverTime, node, users, user, _urlBase, _urlStc, _staticVer, }: IProps): import("react/jsx-runtime").JSX.Element;
58
52
  export {};
@@ -20,9 +20,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
20
20
  * 如需打包为 .bundle.js,执行:node ./source/main build
21
21
  *
22
22
  * 【Tailwind CSS 构建】
23
- * bundle 模式下不再加载 CDN,需提前构建 CSS 产物。
24
- * 执行 node ./source/main build 时会自动构建同名 .css,无需单独执行。
25
- * 框架通过 _urlStc _staticVer 自动拼接正确的带版本号 URL。
23
+ * 需提前执行 node ./source/main build -d source/www/example/stc 生成 CSS 产物。
24
+ * 框架通过 _staticPath _staticVer 自动拼接带版本号 URL;
25
+ * import map、props JSON、水合脚本均由框架自动注入 HTML,组件无需手动处理。
26
26
  */
27
27
  import { useState, useEffect } from 'react';
28
28
  import { Routes, Route, Link, NavLink, useParams, useNavigate, useLocation, Outlet } from 'react-router-dom';
@@ -135,8 +135,6 @@ function PageNotFound() {
135
135
  * 框架负责用 StaticRouter(服务端)/ BrowserRouter(客户端)包裹本组件,
136
136
  * 组件内部只需使用 Routes/Route/Link 等,无需自行包裹 Router。
137
137
  */
138
- export default function ReactRouterPage({ title, serverTime, node, users, user, _urlBase, _urlStc, _staticVer, _importMapJson, _hydrateScript, _propsJson, }) {
139
- return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charSet: "UTF-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { suppressHydrationWarning: true, children: title }), _importMapJson
140
- ? _jsx("script", { src: "https://cdn.tailwindcss.com" })
141
- : _jsx("link", { rel: "stylesheet", href: `${_urlStc}view/react-router-page.css?v=${_staticVer}` }), _importMapJson && (_jsx("script", { type: "importmap", dangerouslySetInnerHTML: { '__html': _importMapJson } }))] }), _jsxs("body", { className: "bg-slate-50 min-h-screen", children: [_jsxs("div", { className: "max-w-2xl mx-auto px-4 py-10 space-y-6", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-bold text-slate-900", children: "Kebab React Router" }), _jsxs("p", { className: "text-slate-500 mt-1 text-sm", children: [_jsx("code", { className: "bg-slate-100 px-1.5 py-0.5 rounded font-mono text-xs", children: "router: 'browser'" }), "\u00A0mode \u2014 URL synced with routes"] })] }), _jsx("a", { href: `${_urlBase}`, className: "text-xs text-slate-400 hover:text-slate-600 transition-colors mt-1", children: "Back to Index" })] }), _jsx("div", { className: "bg-white rounded-xl shadow-sm border border-slate-200 px-4 py-3", children: _jsx(NavBar, {}) }), _jsx("div", { className: "bg-white rounded-xl shadow-sm border border-slate-200 p-6", children: _jsxs(Routes, { children: [_jsx(Route, { path: "/", element: _jsx(PageHome, { serverTime: serverTime, node: node }) }), _jsx(Route, { path: "/about", element: _jsx(PageAbout, {}) }), _jsx(Route, { path: "/user", element: _jsx(PageUsers, { users: users, urlBase: _urlBase }) }), _jsx(Route, { path: "/user/:id", element: _jsx(PageUserDetail, { user: user, urlBase: _urlBase }), children: _jsx(Route, { path: "profile", element: _jsx(PageUserProfile, {}) }) }), _jsx(Route, { path: "*", element: _jsx(PageNotFound, {}) })] }) }), _jsxs(Card, { className: "text-xs text-slate-500 space-y-1.5", children: [_jsx("p", { className: "font-semibold text-slate-700 text-sm", children: "How It Works" }), _jsxs("p", { children: ["\u2022 Server: framework wraps with ", _jsx("code", { className: "bg-slate-100 px-1 rounded", children: "StaticRouter" }), " to SSR the matching route"] }), _jsxs("p", { children: ["\u2022 Client: hydration script wraps with ", _jsx("code", { className: "bg-slate-100 px-1 rounded", children: "BrowserRouter" }), " for URL-synced navigation"] }), _jsxs("p", { children: ["\u2022 Data: one backend method (", _jsx("code", { className: "bg-slate-100 px-1 rounded", children: "_getRouteData" }), ") serves both SSR props and SPA API"] }), _jsxs("p", { children: ["\u2022 Deep links like ", _jsx("code", { className: "bg-slate-100 px-1 rounded", children: "/test/react-router-page/user/42" }), " work out of the box"] })] })] }), _propsJson && (_jsx("script", { id: "__kebab_props__", type: "application/json", suppressHydrationWarning: true, dangerouslySetInnerHTML: { '__html': _propsJson } })), _hydrateScript && (_jsx("script", { type: "module", suppressHydrationWarning: true, dangerouslySetInnerHTML: { '__html': _hydrateScript } }))] })] }));
138
+ export default function ReactRouterPage({ title, serverTime, node, users, user, _urlBase, _urlStc, _staticVer, }) {
139
+ return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charSet: "UTF-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { suppressHydrationWarning: true, children: title }), _jsx("link", { rel: "stylesheet", href: `${_urlStc}view/react-router-page.css?v=${_staticVer}` })] }), _jsx("body", { className: "bg-slate-50 min-h-screen", children: _jsxs("div", { className: "max-w-2xl mx-auto px-4 py-10 space-y-6", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-bold text-slate-900", children: "Kebab React Router" }), _jsxs("p", { className: "text-slate-500 mt-1 text-sm", children: [_jsx("code", { className: "bg-slate-100 px-1.5 py-0.5 rounded font-mono text-xs", children: "router: 'browser'" }), "\u00A0mode \u2014 URL synced with routes"] })] }), _jsx("a", { href: `${_urlBase}`, className: "text-xs text-slate-400 hover:text-slate-600 transition-colors mt-1", children: "Back to Index" })] }), _jsx("div", { className: "bg-white rounded-xl shadow-sm border border-slate-200 px-4 py-3", children: _jsx(NavBar, {}) }), _jsx("div", { className: "bg-white rounded-xl shadow-sm border border-slate-200 p-6", children: _jsxs(Routes, { children: [_jsx(Route, { path: "/", element: _jsx(PageHome, { serverTime: serverTime, node: node }) }), _jsx(Route, { path: "/about", element: _jsx(PageAbout, {}) }), _jsx(Route, { path: "/user", element: _jsx(PageUsers, { users: users, urlBase: _urlBase }) }), _jsx(Route, { path: "/user/:id", element: _jsx(PageUserDetail, { user: user, urlBase: _urlBase }), children: _jsx(Route, { path: "profile", element: _jsx(PageUserProfile, {}) }) }), _jsx(Route, { path: "*", element: _jsx(PageNotFound, {}) })] }) }), _jsxs(Card, { className: "text-xs text-slate-500 space-y-1.5", children: [_jsx("p", { className: "font-semibold text-slate-700 text-sm", children: "How It Works" }), _jsxs("p", { children: ["\u2022 Server: framework wraps with ", _jsx("code", { className: "bg-slate-100 px-1 rounded", children: "StaticRouter" }), " to SSR the matching route"] }), _jsxs("p", { children: ["\u2022 Client: hydration script wraps with ", _jsx("code", { className: "bg-slate-100 px-1 rounded", children: "BrowserRouter" }), " for URL-synced navigation"] }), _jsxs("p", { children: ["\u2022 Data: one backend method (", _jsx("code", { className: "bg-slate-100 px-1 rounded", children: "_getRouteData" }), ") serves both SSR props and SPA API"] }), _jsxs("p", { children: ["\u2022 Deep links like ", _jsx("code", { className: "bg-slate-100 px-1 rounded", children: "/test/react-router-page/user/42" }), " work out of the box"] })] })] }) })] }));
142
140
  }
@@ -19,9 +19,9 @@
19
19
  * 如需打包为 .bundle.js,执行:node ./source/main build
20
20
  *
21
21
  * 【Tailwind CSS 构建】
22
- * bundle 模式下不再加载 CDN,需提前构建 CSS 产物。
23
- * 执行 node ./source/main build 时会自动构建同名 .css,无需单独执行。
24
- * 框架通过 _urlStc _staticVer 自动拼接正确的带版本号 URL。
22
+ * 需提前执行 node ./source/main build -d source/www/example/stc 生成 CSS 产物。
23
+ * 框架通过 _staticPath _staticVer 自动拼接带版本号 URL;
24
+ * import map、props JSON、水合脚本均由框架自动注入 HTML,组件无需手动处理。
25
25
  */
26
26
 
27
27
  import { useState, useEffect } from 'react';
@@ -49,12 +49,6 @@ interface IProps {
49
49
  '_staticVer': string;
50
50
  /** --- 框架注入:BrowserRouter 的 basename,如 /test/react-router-page --- */
51
51
  '_routerBase'?: string;
52
- /** --- 框架注入:import map JSON 字符串 --- */
53
- '_importMapJson'?: string;
54
- /** --- 框架注入:水合脚本 --- */
55
- '_hydrateScript'?: string;
56
- /** --- 框架注入:fullProps 序列化 JSON --- */
57
- '_propsJson'?: string;
58
52
  }
59
53
 
60
54
  // --- 基础控件 ---
@@ -334,7 +328,7 @@ function PageNotFound() {
334
328
  * 组件内部只需使用 Routes/Route/Link 等,无需自行包裹 Router。
335
329
  */
336
330
  export default function ReactRouterPage({
337
- title, serverTime, node, users, user, _urlBase, _urlStc, _staticVer, _importMapJson, _hydrateScript, _propsJson,
331
+ title, serverTime, node, users, user, _urlBase, _urlStc, _staticVer,
338
332
  }: IProps) {
339
333
  return (
340
334
  <html lang="en">
@@ -343,14 +337,9 @@ export default function ReactRouterPage({
343
337
  <meta name="viewport" content="width=device-width, initial-scale=1" />
344
338
  {/* eslint-disable-next-line @typescript-eslint/naming-convention */}
345
339
  <title suppressHydrationWarning>{title}</title>
346
- {/* --- CSS:dev 模式(无 bundle)用 Tailwind CDN;bundle 模式加载本地构建产物 --- */}
347
- {_importMapJson
348
- ? <script src="https://cdn.tailwindcss.com" />
349
- : <link rel="stylesheet" href={`${_urlStc}view/react-router-page.css?v=${_staticVer}`} />}
350
- {/* --- import map:让浏览器识别 bare import,esm.sh 自动解析依赖 --- */}
351
- {_importMapJson && (
352
- <script type="importmap" dangerouslySetInnerHTML={{ '__html': _importMapJson }} />
353
- )}
340
+ {/* --- import map 由框架自动注入在此标签前,无需手动添加 --- */}
341
+ {/* --- dev: 需先执行 node ./source/main build -d source/www/example/stc 生成 CSS --- */}
342
+ <link rel="stylesheet" href={`${_urlStc}view/react-router-page.css?v=${_staticVer}`} />
354
343
  </head>
355
344
  <body className="bg-slate-50 min-h-screen">
356
345
  <div className="max-w-2xl mx-auto px-4 py-10 space-y-6">
@@ -403,23 +392,7 @@ export default function ReactRouterPage({
403
392
  </Card>
404
393
  </div>
405
394
 
406
- {/* --- 框架注入:props JSON,供客户端水合读取 --- */}
407
- {_propsJson && (
408
- <script
409
- id="__kebab_props__"
410
- type="application/json"
411
- suppressHydrationWarning
412
- dangerouslySetInnerHTML={{ '__html': _propsJson }}
413
- />
414
- )}
415
- {/* --- 框架注入:水合脚本 --- */}
416
- {_hydrateScript && (
417
- <script
418
- type="module"
419
- suppressHydrationWarning
420
- dangerouslySetInnerHTML={{ '__html': _hydrateScript }}
421
- />
422
- )}
395
+ {/* --- props JSON + 水合脚本由框架自动注入在此标签前,无需手动添加 --- */}
423
396
  </body>
424
397
  </html>
425
398
  );