@orkestrel/scaffold 0.0.92 → 0.0.93
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/dist/bin/main.js +6 -6
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +4 -2
- package/dist/host/agents/skills/enterprise-bootstrap/references/responsive-layout.md +1 -1
- package/dist/host/agents/skills/enterprise-bootstrap/references/utilities.md +3 -3
- package/dist/host/agents/skills/orkestrel-journey/references/statechart.md +1 -1
- package/dist/host/claude/agents/orkestrel.md +5 -5
- package/dist/host/claude/rules/styles.md +5 -0
- package/dist/host/dotfiles/oxlintrc.json +168 -0
- package/dist/host/guides/browser.md +94 -70
- package/dist/host/guides/mcp.md +15 -15
- package/dist/host/guides/pool.md +73 -48
- package/dist/host/guides/probe.md +262 -216
- package/dist/host/guides/router.md +1 -1
- package/dist/host/guides/worker.md +43 -7
- package/dist/host/manifest.json +15 -15
- package/dist/host/tests/config.test.ts +46 -3
- package/dist/src/core/index.cjs +6 -6
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.js +6 -6
- package/dist/src/core/index.js.map +1 -1
- package/package.json +6 -6
|
@@ -361,7 +361,7 @@ These invariants hold across `src/core` / `src/browser` / `src/server` ↔
|
|
|
361
361
|
stated earlier.
|
|
362
362
|
22. **Streaming both ways.** `buildRequest` streams a body-carrying method's
|
|
363
363
|
message into the `Request` through a manual `ReadableStream` pump — a `for
|
|
364
|
-
await` loop over the `IncomingMessage` enqueueing each chunk, with
|
|
364
|
+
await` loop over the `IncomingMessage` enqueueing each chunk, with
|
|
365
365
|
`duplex: 'half'` set as Node's fetch implementation requires for a
|
|
366
366
|
streamed request body; `sendResponse` streams a non-`null` `Response`
|
|
367
367
|
body back to the `ServerResponse` chunk by chunk, ending the target when
|
|
@@ -164,10 +164,14 @@ These invariants hold across `src/core` ↔ `worker.md`:
|
|
|
164
164
|
`null` reaches Queue or Pool validation. Queue's integer timeout contract is preserved:
|
|
165
165
|
`timeout` must be in `0..2_147_483_647` milliseconds, and `0` disables the deadline.
|
|
166
166
|
Queue is constructed successfully before the
|
|
167
|
-
pool option is read, and every declared pool member (`max`, `
|
|
168
|
-
`destroy`, `validate`) is then captured once by direct access,
|
|
169
|
-
non-enumerable structural options. Pool
|
|
170
|
-
|
|
167
|
+
pool option is read, and every declared pool member (`max`, `min`, `restarts`, `watch`,
|
|
168
|
+
`on`, `error`, `create`, `destroy`, `validate`) is then captured once by direct access,
|
|
169
|
+
preserving inherited and non-enumerable structural options. Pool validates the forwarded
|
|
170
|
+
members. Pool `max` defaults to concurrency only when both `max` and `min` are absent.
|
|
171
|
+
With `min`, Pool defaults `max` to `min` and refuses unequal explicit values or a missing
|
|
172
|
+
`restarts` bound. The worker starts the pool at construction, so a floor warms before
|
|
173
|
+
work arrives and can exceed queue concurrency. A spent floor's startup rejection is
|
|
174
|
+
observed internally; acquire reports the pool failure to jobs. `stop` / `abort` / `clear` return the
|
|
171
175
|
queue's exact cleanup barriers. `destroy` installs one stable barrier before it invokes
|
|
172
176
|
queue teardown (including synchronous abort-event reentry), awaits queue then pool
|
|
173
177
|
settlement serially, aggregates the queue's failure and the pool's in that order, and
|
|
@@ -195,7 +199,7 @@ These invariants hold across `src/core` ↔ `worker.md`:
|
|
|
195
199
|
`TResult` infer from the `input` and `result` guards, so a call site needs no type
|
|
196
200
|
argument. The structured-clone boundary is crossed with no `as`: a `Dispatch` narrows each reply
|
|
197
201
|
value through `options.result` (a value that fails it rejects with `'reply did not
|
|
198
|
-
satisfy result guard'`), and the worker side narrows each payload through
|
|
202
|
+
satisfy result guard'`), and the worker side narrows each payload through
|
|
199
203
|
`options.input` (a bad input replies `'input did not satisfy input guard'`) —
|
|
200
204
|
`TInput` / `TResult` are reconstructed by validation, never asserted. A throwing
|
|
201
205
|
caller guard is contained and rejects only that job; the pooled worker remains usable.
|
|
@@ -383,6 +387,33 @@ See [queue.md](queue.md) / [pool.md](pool.md) for the underlying
|
|
|
383
387
|
listener's throw never prevents a sibling listener, and the throw reaches the emitter's
|
|
384
388
|
`error` handler, so a buggy worker observer leaves the inner queue and pool intact.
|
|
385
389
|
|
|
390
|
+
## Pool options
|
|
391
|
+
|
|
392
|
+
The `pool` option takes Pool's resource options and refuses the `capacity` option, so each
|
|
393
|
+
resource serves one job at a time. Pool owns validation of the forwarded options:
|
|
394
|
+
|
|
395
|
+
| Member | Behavior |
|
|
396
|
+
| ---------- | ---------------------------------------------------------------------------------------------------- |
|
|
397
|
+
| `create` | Creates a resource on demand or while filling a configured floor. |
|
|
398
|
+
| `destroy` | Disposes each resource during pool cleanup or loss. |
|
|
399
|
+
| `validate` | Checks an idle resource before reuse. |
|
|
400
|
+
| `max` | Caps pool capacity; defaults to `concurrency` only when `min` is absent. |
|
|
401
|
+
| `min` | Sets a positive safe integer warm floor; Pool defaults `max` to it and requires equality. |
|
|
402
|
+
| `restarts` | Sets the required non-negative safe integer refill bound with `min`; invalid without `min`. |
|
|
403
|
+
| `watch` | Observes each created resource; settlement declares loss while live, and disposal aborts its signal. |
|
|
404
|
+
| `on` | Installs initial pool lifecycle listeners. |
|
|
405
|
+
| `error` | Receives pool listener failures and live watch rejections or throws. |
|
|
406
|
+
|
|
407
|
+
Pool `start()` fills the floor when the worker is constructed. Without `min`, resources remain
|
|
408
|
+
lazy. A `restarts: 1` bound permits another create after the first failure and spends the
|
|
409
|
+
floor after the second failure. Jobs then receive Pool's `create` error with the last cause.
|
|
410
|
+
A resource lost while idle adds a strike even if it served a job before its last release.
|
|
411
|
+
With `min: 1` and `restarts: 0`, that loss spends the floor, and the next job rejects with
|
|
412
|
+
Pool's `create` error without creating a replacement.
|
|
413
|
+
Worker `start()` restarts queue loops only; it does not reset a spent pool's restart bound.
|
|
414
|
+
See [Pool](pool.md), under “Warm floor and loss”, for refill, retained
|
|
415
|
+
cleanup failures, and watch listener cleanup.
|
|
416
|
+
|
|
386
417
|
## Patterns
|
|
387
418
|
|
|
388
419
|
### A resource-backed worker
|
|
@@ -479,8 +510,9 @@ Follow these practices when you run a worker in production:
|
|
|
479
510
|
- **Honour `context.signal`** — pass it through to the resource's operation and bail
|
|
480
511
|
out when it fires, so timeouts and aborts actually stop work rather than abandoning
|
|
481
512
|
its result.
|
|
482
|
-
- **Size the pool through `concurrency`** —
|
|
483
|
-
`
|
|
513
|
+
- **Size the pool through `concurrency`** — when neither `pool.max` nor `pool.min` is given,
|
|
514
|
+
the pool's `max` defaults to it. Set `pool.max` for a separate lazy resource cap, or
|
|
515
|
+
`pool.min` with `pool.restarts` for a warm floor independent of queue concurrency.
|
|
484
516
|
Concurrency must be a positive safe integer; invalid values are rejected by Queue and
|
|
485
517
|
are never normalized.
|
|
486
518
|
- **`abort` is terminal** — a worker-level abort cancels in-flight work and stops the
|
|
@@ -524,6 +556,10 @@ These tests pin the behaviour this guide documents:
|
|
|
524
556
|
returns the queue's cleanup barriers; constructor options and every declared pool option are
|
|
525
557
|
captured once (including inherited / non-enumerable structural options), only explicit
|
|
526
558
|
`undefined` defaults, runtime `null` reaches the Queue/Pool diagnostic,
|
|
559
|
+
the pool option type excludes `capacity`, `min` warms before work with Pool's `max` default,
|
|
560
|
+
`restarts` bounds failed creates and loss of a previously used idle resource,
|
|
561
|
+
`watch` receives each resource and an abort signal before disposal, conflicting `min`
|
|
562
|
+
and `max` values refuse at construction with Pool's error,
|
|
527
563
|
and invalid Queue concurrency wins before the pool option is read; strict concurrency
|
|
528
564
|
rejects zero, negative, fractional, `NaN`, and infinite values instead of normalizing
|
|
529
565
|
them; `destroy` keeps one
|
package/dist/host/manifest.json
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"storage": "agents/skills/enterprise-bootstrap/references/bootstrap-reference.md",
|
|
35
35
|
"destination": ".agents/skills/enterprise-bootstrap/references/bootstrap-reference.md",
|
|
36
36
|
"executable": false,
|
|
37
|
-
"digest": "
|
|
37
|
+
"digest": "5fe9a1fc675fa566e44816cedf0a8421f387a5276409000ea20c98c876e3ac80"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"storage": "agents/skills/enterprise-bootstrap/references/color-modes.md",
|
|
@@ -70,13 +70,13 @@
|
|
|
70
70
|
"storage": "agents/skills/enterprise-bootstrap/references/responsive-layout.md",
|
|
71
71
|
"destination": ".agents/skills/enterprise-bootstrap/references/responsive-layout.md",
|
|
72
72
|
"executable": false,
|
|
73
|
-
"digest": "
|
|
73
|
+
"digest": "f401dd3aa97b1098a6d97c8862bc7be7713a8a98ae1546a918abb66ee25cd8ad"
|
|
74
74
|
},
|
|
75
75
|
{
|
|
76
76
|
"storage": "agents/skills/enterprise-bootstrap/references/utilities.md",
|
|
77
77
|
"destination": ".agents/skills/enterprise-bootstrap/references/utilities.md",
|
|
78
78
|
"executable": false,
|
|
79
|
-
"digest": "
|
|
79
|
+
"digest": "84a7c3eec5d280ba67b103418a69b4643434b9fa9fe39ee8c1b305f1ba4f94c0"
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
82
|
"storage": "agents/skills/orkestrel-align/SKILL.md",
|
|
@@ -322,7 +322,7 @@
|
|
|
322
322
|
"storage": "agents/skills/orkestrel-journey/references/statechart.md",
|
|
323
323
|
"destination": ".agents/skills/orkestrel-journey/references/statechart.md",
|
|
324
324
|
"executable": false,
|
|
325
|
-
"digest": "
|
|
325
|
+
"digest": "b5866b5a756e2b42feb24e7ea2bdcb7c2c0ecc8d9863488263aeddffb63a44da"
|
|
326
326
|
},
|
|
327
327
|
{
|
|
328
328
|
"storage": "agents/skills/orkestrel-journey/references/styles.md",
|
|
@@ -496,7 +496,7 @@
|
|
|
496
496
|
"storage": "claude/agents/orkestrel.md",
|
|
497
497
|
"destination": ".claude/agents/orkestrel.md",
|
|
498
498
|
"executable": false,
|
|
499
|
-
"digest": "
|
|
499
|
+
"digest": "7c081ea4deffe54305f4a43685adbde2a5941d4f69c3ed386690ab409372a638"
|
|
500
500
|
},
|
|
501
501
|
{
|
|
502
502
|
"storage": "claude/agents/planner.md",
|
|
@@ -580,7 +580,7 @@
|
|
|
580
580
|
"storage": "claude/rules/styles.md",
|
|
581
581
|
"destination": ".claude/rules/styles.md",
|
|
582
582
|
"executable": false,
|
|
583
|
-
"digest": "
|
|
583
|
+
"digest": "156572b7c26740411e64726255f76e0f6e6e4e55e800a26262a923210866eb77"
|
|
584
584
|
},
|
|
585
585
|
{
|
|
586
586
|
"storage": "claude/rules/tests.md",
|
|
@@ -826,7 +826,7 @@
|
|
|
826
826
|
"storage": "dotfiles/oxlintrc.json",
|
|
827
827
|
"destination": ".oxlintrc.json",
|
|
828
828
|
"executable": false,
|
|
829
|
-
"digest": "
|
|
829
|
+
"digest": "c3777d98a2c48a4007397ef90912b2530d7e40bc4d2f85155830e6d1135dc241"
|
|
830
830
|
},
|
|
831
831
|
{
|
|
832
832
|
"storage": "dotfiles/prettierignore",
|
|
@@ -862,7 +862,7 @@
|
|
|
862
862
|
"storage": "guides/browser.md",
|
|
863
863
|
"destination": "guides/browser.md",
|
|
864
864
|
"executable": false,
|
|
865
|
-
"digest": "
|
|
865
|
+
"digest": "dfeb5feef6751bac487cf0205736a6763995b259ef1ee9bee8a606bb12f50e33"
|
|
866
866
|
},
|
|
867
867
|
{
|
|
868
868
|
"storage": "guides/budget.md",
|
|
@@ -952,7 +952,7 @@
|
|
|
952
952
|
"storage": "guides/mcp.md",
|
|
953
953
|
"destination": "guides/mcp.md",
|
|
954
954
|
"executable": false,
|
|
955
|
-
"digest": "
|
|
955
|
+
"digest": "d7363cdbde8cde24503915b0fdc78e30543e3b81e68e105500dfda3ffee7702e"
|
|
956
956
|
},
|
|
957
957
|
{
|
|
958
958
|
"storage": "guides/middleware.md",
|
|
@@ -982,13 +982,13 @@
|
|
|
982
982
|
"storage": "guides/pool.md",
|
|
983
983
|
"destination": "guides/pool.md",
|
|
984
984
|
"executable": false,
|
|
985
|
-
"digest": "
|
|
985
|
+
"digest": "a8bbdd91006afeb577d9e43a3f04ffe37cae989db954058b2e67197a3ca62572"
|
|
986
986
|
},
|
|
987
987
|
{
|
|
988
988
|
"storage": "guides/probe.md",
|
|
989
989
|
"destination": "guides/probe.md",
|
|
990
990
|
"executable": false,
|
|
991
|
-
"digest": "
|
|
991
|
+
"digest": "11ddbf59ab6dd29e24f25ad1076dd6976b6e3bcdda1d95cb5186871b082ce560"
|
|
992
992
|
},
|
|
993
993
|
{
|
|
994
994
|
"storage": "guides/process.md",
|
|
@@ -1036,7 +1036,7 @@
|
|
|
1036
1036
|
"storage": "guides/router.md",
|
|
1037
1037
|
"destination": "guides/router.md",
|
|
1038
1038
|
"executable": false,
|
|
1039
|
-
"digest": "
|
|
1039
|
+
"digest": "890c46d9749875a48f5ec1981e9a8da90c93ad961b2ed092549172d83546f4e9"
|
|
1040
1040
|
},
|
|
1041
1041
|
{
|
|
1042
1042
|
"storage": "guides/scaffold.md",
|
|
@@ -1126,7 +1126,7 @@
|
|
|
1126
1126
|
"storage": "guides/worker.md",
|
|
1127
1127
|
"destination": "guides/worker.md",
|
|
1128
1128
|
"executable": false,
|
|
1129
|
-
"digest": "
|
|
1129
|
+
"digest": "441c0c0a3a5b425fb91034d953e2e6a1d05d3dcb29702c600a43e048bac24afd"
|
|
1130
1130
|
},
|
|
1131
1131
|
{
|
|
1132
1132
|
"storage": "guides/workflow.md",
|
|
@@ -1168,7 +1168,7 @@
|
|
|
1168
1168
|
"storage": "tests/config.test.ts",
|
|
1169
1169
|
"destination": "tests/config.test.ts",
|
|
1170
1170
|
"executable": false,
|
|
1171
|
-
"digest": "
|
|
1171
|
+
"digest": "6d5079e1eed5b45c74ef788c966527e336444f32dc15afde19b7ae360e046854"
|
|
1172
1172
|
},
|
|
1173
1173
|
{
|
|
1174
1174
|
"storage": "tests/policy.test.ts",
|
|
@@ -2144,5 +2144,5 @@
|
|
|
2144
2144
|
]
|
|
2145
2145
|
}
|
|
2146
2146
|
],
|
|
2147
|
-
"digest": "
|
|
2147
|
+
"digest": "561d787211d1f705e038c6ae37fb2ceaf3d9aa147444ec06d90a129ca9c46966"
|
|
2148
2148
|
}
|
|
@@ -2595,7 +2595,7 @@ createSomething({
|
|
|
2595
2595
|
const pattern = readConfigRecord(patternValue)
|
|
2596
2596
|
const message = pattern.message
|
|
2597
2597
|
if (typeof message !== 'string') throw new Error('Missing pattern message')
|
|
2598
|
-
|
|
2598
|
+
let sources: ReadonlyArray<readonly [string, boolean]> = message.includes('URL schemes')
|
|
2599
2599
|
? [
|
|
2600
2600
|
['https://host/x', true],
|
|
2601
2601
|
['data:text/plain,x', true],
|
|
@@ -2661,6 +2661,24 @@ createSomething({
|
|
|
2661
2661
|
true,
|
|
2662
2662
|
],
|
|
2663
2663
|
]
|
|
2664
|
+
if (message.includes('another styles face')) {
|
|
2665
|
+
const face =
|
|
2666
|
+
typeof pattern.regex === 'string'
|
|
2667
|
+
? /@src\/(bootstrap|tailwindcss|styles)\(/u.exec(pattern.regex)?.[1]
|
|
2668
|
+
: undefined
|
|
2669
|
+
if (face === undefined) throw new Error('Missing styles face in restriction pattern')
|
|
2670
|
+
sources = [
|
|
2671
|
+
[`@src/${face}`, true],
|
|
2672
|
+
[`@src/${face}?raw`, true],
|
|
2673
|
+
[`@orkestrel/x/${face}`, true],
|
|
2674
|
+
[`../${face}/index.js`, true],
|
|
2675
|
+
[`../src/${face}/index.js`, true],
|
|
2676
|
+
[`../../src/${face}/index.js`, true],
|
|
2677
|
+
['@src/browser', false],
|
|
2678
|
+
[`@src/${face}x`, false],
|
|
2679
|
+
[`../${face}.ext/index.js`, false],
|
|
2680
|
+
]
|
|
2681
|
+
}
|
|
2664
2682
|
const owner =
|
|
2665
2683
|
Array.isArray(block.files) && typeof block.files[0] === 'string'
|
|
2666
2684
|
? block.files[0].split('/**')[0]
|
|
@@ -2730,6 +2748,9 @@ createSomething({
|
|
|
2730
2748
|
'src/vue',
|
|
2731
2749
|
'app/vue',
|
|
2732
2750
|
'src/browser',
|
|
2751
|
+
'src/bootstrap',
|
|
2752
|
+
'src/tailwindcss',
|
|
2753
|
+
'src/styles',
|
|
2733
2754
|
'app/browser',
|
|
2734
2755
|
'src/core',
|
|
2735
2756
|
'app/core',
|
|
@@ -2737,7 +2758,7 @@ createSomething({
|
|
|
2737
2758
|
'app/server',
|
|
2738
2759
|
'src/bin',
|
|
2739
2760
|
]) {
|
|
2740
|
-
const refused = owner.endsWith('/vue')
|
|
2761
|
+
const refused: Array<string | readonly [string, string]> = owner.endsWith('/vue')
|
|
2741
2762
|
? [
|
|
2742
2763
|
'node:fs',
|
|
2743
2764
|
'@src/server',
|
|
@@ -2773,6 +2794,24 @@ createSomething({
|
|
|
2773
2794
|
: []),
|
|
2774
2795
|
]
|
|
2775
2796
|
: ['@src/core']
|
|
2797
|
+
if (owner === 'src/core') refused.push('@src/browser', './index.css')
|
|
2798
|
+
if (['src/bootstrap', 'src/tailwindcss', 'src/styles'].includes(owner)) {
|
|
2799
|
+
refused.push('node:fs', '@src/server', '../server/index.js', '@app/core')
|
|
2800
|
+
for (const face of ['bootstrap', 'tailwindcss', 'styles']) {
|
|
2801
|
+
if (owner === `src/${face}`) continue
|
|
2802
|
+
refused.push(
|
|
2803
|
+
`@src/${face}`,
|
|
2804
|
+
`@orkestrel/x/${face}`,
|
|
2805
|
+
`../${face}/index.js`,
|
|
2806
|
+
`../src/${face}/index.js`,
|
|
2807
|
+
`../../src/${face}/index.js`,
|
|
2808
|
+
['export * from', `@src/${face}`],
|
|
2809
|
+
['import type * as boundary from', `@src/${face}`],
|
|
2810
|
+
)
|
|
2811
|
+
admitted.push(`@src/${face}x`, `../${face}.ext/index.js`)
|
|
2812
|
+
}
|
|
2813
|
+
admitted.push('@src/browser', './sheet.js', '@orkestrel/contract')
|
|
2814
|
+
}
|
|
2776
2815
|
for (const [sources, refusal] of [
|
|
2777
2816
|
[
|
|
2778
2817
|
[
|
|
@@ -2799,7 +2838,11 @@ createSomething({
|
|
|
2799
2838
|
mkdirSync(dirname(resolve(scratch, file)), { recursive: true })
|
|
2800
2839
|
writeFileSync(
|
|
2801
2840
|
resolve(scratch, file),
|
|
2802
|
-
|
|
2841
|
+
typeof source === 'string'
|
|
2842
|
+
? 'import * as boundary from ' +
|
|
2843
|
+
JSON.stringify(source) +
|
|
2844
|
+
'\nvoid boundary\ndebugger\n'
|
|
2845
|
+
: source[0] + ' ' + JSON.stringify(source[1]) + '\ndebugger\n',
|
|
2803
2846
|
)
|
|
2804
2847
|
expected.set(file, refusal)
|
|
2805
2848
|
}
|
package/dist/src/core/index.cjs
CHANGED
|
@@ -4,7 +4,7 @@ let _orkestrel_template = require("@orkestrel/template");
|
|
|
4
4
|
let _orkestrel_emitter = require("@orkestrel/emitter");
|
|
5
5
|
var package_default = {
|
|
6
6
|
name: "@orkestrel/scaffold",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.93",
|
|
8
8
|
description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
|
|
9
9
|
keywords: [
|
|
10
10
|
"audit",
|
|
@@ -103,16 +103,16 @@ var package_default = {
|
|
|
103
103
|
"@orkestrel/template": "^0.0.9"
|
|
104
104
|
},
|
|
105
105
|
devDependencies: {
|
|
106
|
-
"@microsoft/api-extractor": "^7.59.
|
|
107
|
-
"@orkestrel/browser": "^0.0.
|
|
106
|
+
"@microsoft/api-extractor": "^7.59.4",
|
|
107
|
+
"@orkestrel/browser": "^0.0.26",
|
|
108
108
|
"@orkestrel/guide": "^0.0.24",
|
|
109
109
|
"@orkestrel/html": "^0.0.12",
|
|
110
|
-
"@orkestrel/probe": "^0.0.
|
|
110
|
+
"@orkestrel/probe": "^0.0.21",
|
|
111
111
|
"@orkestrel/test": "^0.0.24",
|
|
112
112
|
"@types/node": "^26.6.4",
|
|
113
113
|
"@vitest/browser-playwright": "^4.1.11",
|
|
114
|
-
"oxfmt": "^0.
|
|
115
|
-
"oxlint": "^1.
|
|
114
|
+
"oxfmt": "^0.72.0",
|
|
115
|
+
"oxlint": "^1.87.0",
|
|
116
116
|
"playwright": "^1.63.0",
|
|
117
117
|
"typescript": "^6.0.3",
|
|
118
118
|
"vite": "^8.3.2",
|