gofront 0.0.6 → 0.0.8
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 +104 -33
- package/package.json +12 -5
- package/src/codegen/expressions.js +603 -9
- package/src/codegen/source-map.js +8 -5
- package/src/codegen/statements.js +30 -26
- package/src/codegen.js +119 -8
- package/src/compiler.js +2 -1
- package/src/dev-server.js +1 -0
- package/src/index.js +1 -1
- package/src/parser.js +0 -10
- package/src/resolver.js +29 -0
- package/src/typechecker/expressions.js +38 -9
- package/src/typechecker/stdlib.js +1067 -0
- package/src/typechecker/types.js +13 -33
- package/src/typechecker.js +25 -601
package/README.md
CHANGED
|
@@ -101,8 +101,8 @@ Walks the typed AST and emits clean, readable JavaScript. No intermediate repres
|
|
|
101
101
|
— the codegen writes directly to an output buffer with indentation tracking.
|
|
102
102
|
|
|
103
103
|
Runtime helpers (`__len`, `__append`, `__s`, `__sprintf`, `__cmul`, `__cdiv`, `__error`,
|
|
104
|
-
`__errorIs`) are tree-shaken: only emitted
|
|
105
|
-
maps are supported via VLQ-encoded mappings.
|
|
104
|
+
`__errorIs`, `__timeFmt`, `__timeParse`, `__pathClean`) are tree-shaken: only emitted
|
|
105
|
+
when actually used. Optional inline source maps are supported via VLQ-encoded mappings.
|
|
106
106
|
|
|
107
107
|
---
|
|
108
108
|
|
|
@@ -184,7 +184,7 @@ The type checker enforces correctness; JavaScript doesn't need to know.
|
|
|
184
184
|
|
|
185
185
|
## Examples — Todo App
|
|
186
186
|
|
|
187
|
-
There are
|
|
187
|
+
There are three example apps — all implement the same todo app to show different aspects
|
|
188
188
|
of GoFront.
|
|
189
189
|
|
|
190
190
|
### Simple (vanilla DOM)
|
|
@@ -202,7 +202,7 @@ example/simple/
|
|
|
202
202
|
styles.go ← injectStyles() creates <style> element with all CSS
|
|
203
203
|
main.go ← createApp() builds DOM shell · setupEvents() · event delegation
|
|
204
204
|
utils/
|
|
205
|
-
utils.go ← Plural() · generic Filter
|
|
205
|
+
utils.go ← Plural() · generic Filter — cross-package import demo
|
|
206
206
|
browser.d.ts ← minimal external type declarations (sleep)
|
|
207
207
|
index.html ← bare HTML shell, loads app.js as ES module
|
|
208
208
|
app.js ← generated output
|
|
@@ -212,41 +212,99 @@ example/simple/
|
|
|
212
212
|
|
|
213
213
|
Same app rebuilt with [reactive.js](https://github.com/seriva/microtastic), a tiny
|
|
214
214
|
signals-based reactive framework. Demonstrates how GoFront integrates with external JS
|
|
215
|
-
libraries via `.d.ts` type declarations — the
|
|
216
|
-
|
|
217
|
-
all described in a hand-written `browser.d.ts` shim.
|
|
215
|
+
libraries via `.d.ts` type declarations — the entire reactive API surface is typed via a
|
|
216
|
+
hand-written `browser.d.ts` shim and exercised from GoFront source.
|
|
218
217
|
|
|
219
218
|
```
|
|
220
219
|
example/reactive/
|
|
221
220
|
src/
|
|
222
221
|
types.go ← Todo, Stats, AppElements structs
|
|
223
|
-
store.go ←
|
|
224
|
-
render.go ←
|
|
225
|
-
styles.go ←
|
|
226
|
-
main.go ←
|
|
222
|
+
store.go ← reactive state: Signals.create/computed/computedAsync/batch/update
|
|
223
|
+
render.go ← Reactive.Component lifecycle · ctx.bind* · setupStatsBar
|
|
224
|
+
styles.go ← per-section cssClass() scoped styles
|
|
225
|
+
main.go ← async boot, Reactive.mount loading placeholder, signal.subscribe/once
|
|
227
226
|
utils/
|
|
228
|
-
utils.go ← Plural() · generic Filter
|
|
229
|
-
browser.d.ts ← Signal
|
|
227
|
+
utils.go ← Plural() · generic Filter
|
|
228
|
+
browser.d.ts ← Signal · ComponentContext · Signals/Reactive namespaces · htmlTag
|
|
230
229
|
reactive.js ← signals framework (from microtastic)
|
|
231
|
-
index.html ← loads reactive.js
|
|
230
|
+
index.html ← loads reactive.js, exposes helpers, imports app.js
|
|
232
231
|
app.js ← generated output
|
|
233
232
|
```
|
|
234
233
|
|
|
234
|
+
The reactive example covers the full reactive.js API surface:
|
|
235
|
+
|
|
236
|
+
| Category | Features used |
|
|
237
|
+
|---|---|
|
|
238
|
+
| HTML helpers | `html` tagged template (via `htmlTag`), `trusted`, `join` |
|
|
239
|
+
| CSS | `cssClass` scoped styles with nested `&` selectors |
|
|
240
|
+
| Signals | `create`, `computed`, `computedAsync`, `batch`, `get`, `peek`, `set`, `update`, `subscribe`, `once` |
|
|
241
|
+
| Reactive namespace | `mount` (loading placeholder), `createComponent`, `scan` |
|
|
242
|
+
| Component context | `bind`, `bindAttr`, `bindBoolAttr`, `bindClass`, `bindText`, `bindStyle`, `bindMultiple`, `computed` |
|
|
243
|
+
| Component lifecycle | `state`, `template`, `styles`, `mount`, `mountTo`, `appendTo`, `refs` (via `data-ref`) |
|
|
244
|
+
| Component instance | `signal`, `effect`, `on` (auto-cleanup event listeners) |
|
|
245
|
+
| Scan attributes | `data-model`, `data-text`, `data-html`, `data-if`, `data-visible`, `data-class-*`, `data-attr-*`, `data-bool-*`, `data-on-*`, `data-ref` |
|
|
246
|
+
|
|
247
|
+
### gom (stdlib component library + todo app)
|
|
248
|
+
|
|
249
|
+
Browser-native declarative DOM components inspired by
|
|
250
|
+
[gomponents](https://www.gomponents.com). `gom` is a **built-in stdlib package** — no
|
|
251
|
+
import path needed, available in every GoFront program just like `fmt` or `strings`. It
|
|
252
|
+
uses **methods on named non-struct types** so that plain functions and slices can satisfy
|
|
253
|
+
the `Node` interface without any struct boilerplate.
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
example/gom/
|
|
257
|
+
src/
|
|
258
|
+
types.go ← Todo struct, filter/priority constants
|
|
259
|
+
store.go ← state, mutations, localStorage persistence
|
|
260
|
+
render.go ← gom node builders (pure node tree, no innerHTML)
|
|
261
|
+
styles.go ← appStyles() CSS string
|
|
262
|
+
main.go ← event setup, submitInput, entry point
|
|
263
|
+
utils/ ← Filter[T], Plural, HasText
|
|
264
|
+
app.js ← generated output
|
|
265
|
+
index.html ← HTML shell
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Key types and functions (all accessed as `gom.*`, no import needed):
|
|
269
|
+
- `gom.Node` — interface with a single `Mount(parent any)` method
|
|
270
|
+
- `gom.NodeFunc` — `type NodeFunc func(parent any)` with `Mount` method; any function becomes a `Node`
|
|
271
|
+
- `gom.Group` — `type Group []Node` with `Mount` method; composes children in order
|
|
272
|
+
- `gom.El(tag, children...)` — creates an element node
|
|
273
|
+
- `gom.Text(s)` — creates a text node
|
|
274
|
+
- `gom.Attr(name, val)` — generic attribute node; named shortcuts: `gom.Class`, `gom.Href`, `gom.Type`, etc.
|
|
275
|
+
- `gom.If(cond, node)` — conditionally renders a node
|
|
276
|
+
- `gom.Map(slice, fn)` — maps a slice to a `Group` of nodes
|
|
277
|
+
- `gom.Style(css)` — returns a `Node` that injects a `<style>` element; styles are part of the node tree
|
|
278
|
+
- `gom.Mount(selector, n)` — mounts a node into the DOM, replacing the element's content
|
|
279
|
+
- `gom.MountTo(selector, n)` — appends a node without clearing; used to inject styles into `<head>`
|
|
280
|
+
- HTML element helpers: `gom.Div`, `gom.Span`, `gom.Button`, `gom.Input`, `gom.Ul`, `gom.Li`, … (full HTML element set)
|
|
281
|
+
|
|
235
282
|
### Features demonstrated
|
|
236
283
|
|
|
237
|
-
|
|
238
|
-
slices, `for range`, `switch`, cross-package imports, multi-file
|
|
239
|
-
`async`/`await`, `defer`/`recover`, localStorage persistence,
|
|
240
|
-
utility functions (`Filter[T]`, `Map[T, U]`).
|
|
284
|
+
The simple and reactive examples cover: structs & methods, iota constants, named return
|
|
285
|
+
values, closures, slices, `for range`, `switch`, cross-package imports, multi-file
|
|
286
|
+
same-package compilation, `async`/`await`, `defer`/`recover`, localStorage persistence,
|
|
287
|
+
DOM APIs, and generic utility functions (`Filter[T]`, `Map[T, U]`).
|
|
241
288
|
|
|
242
289
|
The reactive example additionally demonstrates: external `.d.ts` type imports,
|
|
243
|
-
`declare namespace` patterns for typing JS libraries,
|
|
290
|
+
`declare namespace` patterns for typing JS libraries, the full reactive signal graph
|
|
291
|
+
(source signals → computed signals → async computed → DOM bindings), reactive UI with
|
|
292
|
+
no `querySelector` or `getElementById` in application code, and `Reactive.Component`
|
|
293
|
+
as the primary composition unit (state, template, styles, mount lifecycle, `data-ref`
|
|
294
|
+
element refs, auto-cleanup event listeners).
|
|
295
|
+
|
|
296
|
+
The gom example additionally demonstrates: **the `gom` built-in stdlib package**,
|
|
297
|
+
styles as nodes (`gom.Style` + `gom.MountTo`), `gom.Map` for list rendering, the
|
|
298
|
+
declarative node-tree pattern (no `innerHTML`, no `querySelector`), and full feature
|
|
299
|
+
parity with the other examples (priority mode, validation, localStorage persistence,
|
|
300
|
+
sync status, drag-and-drop reordering).
|
|
244
301
|
|
|
245
302
|
### Build and run
|
|
246
303
|
|
|
247
304
|
```sh
|
|
248
305
|
npm run build:simple # → example/simple/app.js
|
|
249
306
|
npm run build:reactive # → example/reactive/app.js
|
|
307
|
+
npm run build:gom # → example/gom/app.js
|
|
250
308
|
# open the respective index.html in a browser
|
|
251
309
|
```
|
|
252
310
|
|
|
@@ -367,6 +425,7 @@ signatures into GoFront's internal type representation.
|
|
|
367
425
|
| `error` type | ✓ — interface `{ Error() string }`; custom error types, `errors.Is`/`Unwrap`, `%w` wrapping |
|
|
368
426
|
| Complex numbers (`complex64`, `complex128`, `3i`) | ✓ — `complex()`, `real()`, `imag()` builtins; `__cmul`/`__cdiv` helpers |
|
|
369
427
|
| Type definitions, type aliases (`type A = B`) | ✓ |
|
|
428
|
+
| Methods on named non-struct types | ✓ — `type T func(...)` or `type T []E` with methods; emitted as ES6 wrapper classes; satisfies interfaces |
|
|
370
429
|
| Type conversions, type assertions (plain & comma-ok) | ✓ |
|
|
371
430
|
| Type switch (`switch v := x.(type)`) | ✓ — compiles to `if/else if` with `typeof` / `instanceof` |
|
|
372
431
|
| Sized integers (`int8`–`int64`, `uint8`–`uint64`, `float32`) | ✓ — mapped to `number` at runtime |
|
|
@@ -405,20 +464,25 @@ signatures into GoFront's internal type representation.
|
|
|
405
464
|
|
|
406
465
|
| Package | Functions |
|
|
407
466
|
|---|---|
|
|
408
|
-
| `fmt` | `Sprintf`, `Printf`, `Println`, `Print`, `Errorf`, `Fprintf`, `Fprintln`, `Fprint` — format verbs: `%v`, `%d`, `%s`, `%t`, `%x`, `%o`, `%b`, `%q`, `%e`, `%g`, `%w`, width/precision |
|
|
409
|
-
| `strings` | `Contains`, `HasPrefix`, `HasSuffix`, `Index`, `LastIndex`, `Count`, `Repeat`, `Replace`, `ReplaceAll`, `ToUpper`, `ToLower`, `TrimSpace`, `Trim`, `TrimPrefix`, `TrimSuffix`, `TrimLeft`, `TrimRight`, `Split`, `Join`, `EqualFold
|
|
410
|
-
| `bytes` | `Contains`, `HasPrefix`, `HasSuffix`, `Index`, `Join`, `Split`, `Replace`, `ToUpper`, `ToLower`, `TrimSpace`, `Equal`, `Count`, `Repeat
|
|
411
|
-
| `strconv` | `Itoa`, `Atoi`, `FormatBool`, `FormatInt`, `FormatFloat`, `ParseFloat`, `ParseInt`, `ParseBool` |
|
|
412
|
-
| `sort` | `Ints`, `Float64s`, `Strings`, `Slice`, `SliceStable`, `SliceIsSorted` |
|
|
413
|
-
| `math` | `Abs`, `Floor`, `Ceil`, `Round`, `Sqrt`, `Cbrt`, `Pow`, `Log`, `Log2`, `Log10`,
|
|
467
|
+
| `fmt` | `Sprintf`, `Printf`, `Println`, `Print`, `Errorf`, `Fprintf`, `Fprintln`, `Fprint` — format verbs: `%v`, `%d`, `%s`, `%t`, `%x`, `%o`, `%b`, `%q`, `%e`, `%g`, `%w`, width/precision; **scanning**: `Sscan`, `Sscanln`, `Sscanf` |
|
|
468
|
+
| `strings` | `Contains`, `HasPrefix`, `HasSuffix`, `Index`, `LastIndex`, `Count`, `Repeat`, `Replace`, `ReplaceAll`, `ToUpper`, `ToLower`, `TrimSpace`, `Trim`, `TrimPrefix`, `TrimSuffix`, `TrimLeft`, `TrimRight`, `Split`, `Join`, `EqualFold`, `Fields`, `Cut`, `CutPrefix`, `CutSuffix`, `SplitN`, `SplitAfter`, `SplitAfterN`, `IndexAny`, `LastIndexAny`, `ContainsAny`, `ContainsRune`, `IndexRune`, `IndexByte`, `LastIndexByte`, `Map`, `Title`, `ToTitle`, `TrimFunc`, `TrimLeftFunc`, `TrimRightFunc`, `IndexFunc`, `LastIndexFunc`, `NewReplacer`; **`Builder`** type; **`NewReader`** → reader shim |
|
|
469
|
+
| `bytes` | `Contains`, `HasPrefix`, `HasSuffix`, `Index`, `Join`, `Split`, `Replace`, `ToUpper`, `ToLower`, `TrimSpace`, `Equal`, `Count`, `Repeat`, `ReplaceAll`, `TrimPrefix`, `TrimSuffix`, `TrimLeft`, `TrimRight`, `TrimFunc`, `IndexByte`, `LastIndex`, `LastIndexByte`, `Fields`, `Cut`, `ContainsAny`, `ContainsRune`, `Map`, `SplitN`; **`Buffer`** type; **`NewReader`** → reader shim |
|
|
470
|
+
| `strconv` | `Itoa`, `Atoi`, `FormatBool`, `FormatInt`, `FormatFloat`, `ParseFloat`, `ParseInt`, `ParseBool`, `Quote`, `Unquote`, `AppendInt`, `AppendFloat` |
|
|
471
|
+
| `sort` | `Ints`, `Float64s`, `Strings`, `Slice`, `SliceStable`, `SliceIsSorted`, `Search`, `IntsAreSorted`, `Float64sAreSorted`, `StringsAreSorted` |
|
|
472
|
+
| `math` | `Abs`, `Floor`, `Ceil`, `Round`, `Sqrt`, `Cbrt`, `Pow`, `Log`, `Log2`, `Log10`, `Sin`, `Cos`, `Tan`, `Atan`, `Atan2`, `Asin`, `Acos`, `Exp`, `Exp2`, `Trunc`, `Hypot`, `Signbit`, `Copysign`, `Dim`, `Remainder`, `Min`, `Max`, `Mod`, `Inf`, `IsNaN`, `IsInf`, `NaN` + `Pi`, `E`, `MaxFloat64`, `SmallestNonzeroFloat64`, `MaxInt`, `MinInt` |
|
|
473
|
+
| `math/rand` | `Intn`, `Float64`, `Float32`, `Int`, `Int63`, `Int63n`, `Int31`, `Int31n`, `Seed` (no-op), `Shuffle`, `Perm` |
|
|
414
474
|
| `errors` | `New`, `Is`, `Unwrap` — custom error types via interface satisfaction |
|
|
415
|
-
| `time` | `Now`, `Since`, `Sleep`
|
|
475
|
+
| `time` | `Now` → `time.Time`, `Since`, `Sleep`, `Parse`, `Unix`, `Date`; **`time.Time`** methods: `Format`, `String`, `Year`, `Month`, `Day`, `Hour`, `Minute`, `Second`, `Weekday`, `Unix`, `UnixMilli`, `Add`, `Sub`, `Before`, `After`, `Equal`; layout constants: `RFC3339`, `RFC3339Nano`, `DateOnly`, `TimeOnly`, `DateTime`; duration constants: `Millisecond`, `Second`, `Minute`, `Hour`; month/weekday constants |
|
|
416
476
|
| `html` | `EscapeString`, `UnescapeString` |
|
|
417
477
|
| `maps` | `Keys`, `Values`, `Clone`, `Copy`, `Equal`, `EqualFunc`, `Delete`, `DeleteFunc` |
|
|
418
478
|
| `slices` | `Contains`, `Index`, `Equal`, `Compare`, `Sort`, `SortFunc`, `SortStableFunc`, `IsSorted`, `IsSortedFunc`, `Reverse`, `Max`, `Min`, `MaxFunc`, `MinFunc`, `Clone`, `Compact`, `CompactFunc`, `Concat`, `Delete`, `DeleteFunc`, `Insert`, `Replace`, `Grow`, `Clip` |
|
|
419
479
|
| `regexp` | `MustCompile`, `Compile`, `MatchString`, `QuoteMeta`; **`*Regexp`** methods: `MatchString`, `FindString`, `FindStringIndex`, `FindAllString`, `FindStringSubmatch`, `FindAllStringSubmatch`, `ReplaceAllString`, `ReplaceAllLiteralString`, `Split`, `String`. Inline flags (`(?i)`, `(?m)`, `(?s)`) are extracted automatically into the JS `RegExp` constructor. |
|
|
420
480
|
| `unicode` | `IsLetter`, `IsDigit`, `IsSpace`, `IsUpper`, `IsLower`, `IsPunct`, `IsControl`, `IsPrint`, `IsGraphic`, `ToUpper`, `ToLower` |
|
|
481
|
+
| `unicode/utf8` | `RuneCountInString`, `RuneLen`, `ValidString`, `ValidRune`, `DecodeRuneInString`, `DecodeLastRuneInString`, `FullRuneInString`; constants `RuneError`, `MaxRune`, `UTFMax` |
|
|
482
|
+
| `path` | `Base`, `Dir`, `Ext`, `Join`, `Clean`, `IsAbs`, `Split`, `Match`; `"path/filepath"` is an alias |
|
|
421
483
|
| `os` | `Exit`, `Args`, `Getenv` |
|
|
484
|
+
| `io` | `Writer`, `Reader`, `ReadWriter`, `Closer` interface types; `ReadAll`, `EOF`, `Discard`, `WriteString` |
|
|
485
|
+
| `gom` | Browser-native declarative DOM component library. **Types**: `Node` (interface), `NodeFunc`, `Group`. **Core**: `El(tag, children...)`, `Text(s)`, `Mount(sel, node)`, `MountTo(sel, node)`. **Attributes**: `Attr`, `Class`, `Href`, `Type`, `Src`, `Placeholder`, `DataAttr`, `Style`, `For`, `Name`, `Value`, `Target`, `Rel`, `Alt`, `Title`, `Draggable`, `Role`, `AriaLabel`, `StyleAttr`; boolean: `Disabled`, `Checked`, `Selected`, `Readonly`. **Logic**: `If(cond, node)`, `Map(slice, fn)`. **Elements**: full HTML element set (`Div`, `Span`, `Button`, `Input`, `Ul`, `Li`, `Table`, `Form`, `Img`, `A`, `H1`–`H6`, …) |
|
|
422
486
|
|
|
423
487
|
### Packages & imports
|
|
424
488
|
|
|
@@ -490,18 +554,25 @@ you know exactly what to expect.
|
|
|
490
554
|
|
|
491
555
|
See [`docs/ROADMAP.md`](docs/ROADMAP.md) for the full roadmap and release history.
|
|
492
556
|
Design documents for planned features are organised by release under `docs/v*/`
|
|
493
|
-
(e.g. [`docs/v0.0.
|
|
557
|
+
(e.g. [`docs/v0.0.8/`](docs/v0.0.8/), [`docs/v0.0.9/`](docs/v0.0.9/)).
|
|
494
558
|
|
|
495
559
|
---
|
|
496
560
|
|
|
497
561
|
## Tests
|
|
498
562
|
|
|
499
563
|
```sh
|
|
500
|
-
npm test
|
|
564
|
+
npm run test:unit # unit tests only (~1076 tests, no browser required)
|
|
565
|
+
npm run test:e2e # E2E tests (Playwright, headless Chromium)
|
|
566
|
+
npm test # both
|
|
501
567
|
```
|
|
502
568
|
|
|
503
|
-
|
|
504
|
-
`.d.ts`, npm resolver, multi-file compilation, embedded structs, string
|
|
505
|
-
iteration order, integer overflow semantics, unused variable detection,
|
|
506
|
-
detection, semantic difference verification, stdlib shim packages,
|
|
507
|
-
|
|
569
|
+
**Unit tests** (1076) cover language features, type errors, edge cases, DOM (jsdom),
|
|
570
|
+
external `.d.ts`, npm resolver, multi-file compilation, embedded structs, string
|
|
571
|
+
formatting, map iteration order, integer overflow semantics, unused variable detection,
|
|
572
|
+
unused import detection, semantic difference verification, stdlib shim packages, and
|
|
573
|
+
generics.
|
|
574
|
+
|
|
575
|
+
**E2E tests** (74, Playwright) run all three example apps in a real browser and verify
|
|
576
|
+
CRUD, filtering, priority mode, persistence (reload), drag-and-drop reordering, and sync
|
|
577
|
+
status. Per-app suites check app-specific behaviour: scoped styles, stats bar, loading
|
|
578
|
+
placeholder, and `gom.If` conditional rendering.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gofront",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"author": "Luuk van Venrooij",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -33,12 +33,19 @@
|
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build:simple": "node src/index.js example/simple/src -o example/simple/app.js",
|
|
35
35
|
"build:reactive": "node src/index.js example/reactive/src -o example/reactive/app.js",
|
|
36
|
-
"
|
|
36
|
+
"build:gom": "node src/index.js example/gom/src -o example/gom/app.js",
|
|
37
|
+
"test": "npm run test:unit && npm run test:e2e",
|
|
38
|
+
"test:unit": "node test/unit/run.js",
|
|
39
|
+
"test:e2e": "playwright test",
|
|
37
40
|
"format": "biome format --write .",
|
|
38
|
-
"check": "biome check ."
|
|
41
|
+
"check": "biome check . && node src/index.js example/simple/src --check && node src/index.js example/reactive/src --check && node src/index.js example/gom/src --check",
|
|
42
|
+
"prepare": "husky"
|
|
39
43
|
},
|
|
40
44
|
"devDependencies": {
|
|
41
|
-
"@biomejs/biome": "^2.4.
|
|
42
|
-
"
|
|
45
|
+
"@biomejs/biome": "^2.4.12",
|
|
46
|
+
"@playwright/test": "^1.59.1",
|
|
47
|
+
"husky": "^9.1.7",
|
|
48
|
+
"jsdom": "^29.0.2",
|
|
49
|
+
"serve": "^14.2.6"
|
|
43
50
|
}
|
|
44
51
|
}
|