@krak-stack/registry 0.1.41 → 0.1.43

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 CHANGED
@@ -6,41 +6,19 @@ Tree-shakable runtime components and Effect services from the KrakStack shadcn r
6
6
  bun add @krak-stack/registry
7
7
  ```
8
8
 
9
- ## Temporary Effect form patches
9
+ ## Effect forms
10
10
 
11
- This interim release supports stable Effect 4, but the published form betas still
12
- use removed Effect import paths. Applications using Effect forms must apply both
13
- compatibility patches at their package-manager root; installing Registry alone
14
- does not apply them automatically.
15
-
16
- After installing Registry, copy its bundled patches into your application:
11
+ Applications using Effect forms need `@lucas-barake/effect-form@1.1.0` and
12
+ `@lucas-barake/effect-form-react@1.1.0`, which support stable Effect 4 without
13
+ compatibility patches:
17
14
 
18
15
  ```sh
19
- mkdir -p patches
20
- cp node_modules/@krak-stack/registry/patches/*.patch patches/
21
- ```
22
-
23
- Merge these fields into the application's root `package.json`, preserving any
24
- existing overrides and patches:
25
-
26
- ```json
27
- {
28
- "overrides": {
29
- "@lucas-barake/effect-form": "0.25.0-beta.6",
30
- "@lucas-barake/effect-form-react": "0.26.0-beta.5"
31
- },
32
- "patchedDependencies": {
33
- "@lucas-barake/effect-form@0.25.0-beta.6": "patches/@lucas-barake%2Feffect-form@0.25.0-beta.6.patch",
34
- "@lucas-barake/effect-form-react@0.26.0-beta.5": "patches/@lucas-barake%2Feffect-form-react@0.26.0-beta.5.patch"
35
- }
36
- }
16
+ bun add @lucas-barake/effect-form@1.1.0 @lucas-barake/effect-form-react@1.1.0
37
17
  ```
38
18
 
39
- Run `bun install` and commit the patches, manifest, and lockfile. Other package
40
- managers require equivalent patch configuration. See the bundled
41
- `patches/README.md` for provenance and removal instructions after
42
- [upstream release PR #111](https://github.com/lucas-barake/effect-form/pull/111)
43
- is published.
19
+ When upgrading from the patched betas, remove their `patchedDependencies`
20
+ entries and patch files, update any form version overrides to `1.1.0`, and run
21
+ `bun install`. Preserve unrelated dependency patches.
44
22
 
45
23
  ## Usage
46
24
 
@@ -79,182 +57,191 @@ import {
79
57
  import { NotificationService } from "@krak-stack/registry/service-notification";
80
58
  ```
81
59
 
82
- Inject API telemetry and browser proxy routes into the application HTTP layer:
60
+ ## OpenTelemetry
61
+
62
+ | Export | Purpose |
63
+ | --------------------------------------------------------- | --------------------------------------------------------------------------------------- |
64
+ | `HttpApiOtlp.layer` from `opentelemetry/api` | Server exporters and same-origin browser ingestion routes. Includes `ServerOtlp.layer`. |
65
+ | `ServerOtlp.layer` from `opentelemetry/server` | Exporters for workers, workflows, and CLIs without an HTTP server. |
66
+ | `BrowserOtlp.layer(options)` from `opentelemetry/browser` | Browser tracing and optional events, logs, and metrics. |
67
+
68
+ ### Setup
69
+
70
+ Provide the HTTP layer once at the application composition root:
83
71
 
84
72
  ```ts
73
+ import { Layer } from "effect";
74
+ import { HttpApiOtlp } from "@krak-stack/registry/opentelemetry/api";
75
+
85
76
  const appLayer = appRoutes.pipe(Layer.provideMerge(HttpApiOtlp.layer));
86
77
  ```
87
78
 
88
- Install browser telemetry globally on the Atom runtime used by the API client:
79
+ Configure an OTLP/HTTP collector on the server:
80
+
81
+ ```dotenv
82
+ OTEL_SERVICE_NAME=my-app-api
83
+ OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
84
+ OTEL_TRACES_EXPORTER=otlp
85
+ OTEL_METRICS_EXPORTER=otlp
86
+ OTEL_LOGS_EXPORTER=otlp
87
+ ```
88
+
89
+ Browser events require the logs signal. The proxy forwards enabled signals from
90
+ `/api/otel/v1/{traces,metrics,logs}` to the collector. Keep collector credentials
91
+ server-side. Server log endpoint/header overrides use
92
+ `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` / `OTEL_EXPORTER_OTLP_LOGS_HEADERS`, falling
93
+ back to the shared endpoint/headers; these overrides do not change proxy routing.
94
+ `OTEL_SDK_DISABLED=true` disables server export, not browser collection.
95
+
96
+ Install one browser layer on the Atom context passed to `AtomHttpApi.Service`:
89
97
 
90
98
  ```ts
91
99
  import { Atom } from "effect/reactivity";
92
100
  import { BrowserOtlp } from "@krak-stack/registry/opentelemetry/browser";
93
101
 
94
102
  const apiRuntime = Atom.context();
95
-
96
103
  if (!import.meta.env.SSR) {
97
- apiRuntime.addGlobalLayer(BrowserOtlp.layer({ serviceName: "my-app-web" }));
104
+ apiRuntime.addGlobalLayer(
105
+ BrowserOtlp.layer({ serviceName: "my-app-web", events: {} }),
106
+ );
98
107
  }
99
108
  ```
100
109
 
101
- ### Named events and page views
110
+ Mount/read `ApiClient.runtime` in the root layout to start it. Browser methods
111
+ target the active layer even when run from another Effect runtime. Calls before
112
+ startup or after disposal are no-ops, not buffered. Dispose long-lived server and
113
+ browser runtimes on shutdown to flush pending data.
102
114
 
103
- For workers, workflows, or CLIs without an HTTP server, provide `ServerOtlp.layer`
104
- from `@krak-stack/registry/opentelemetry/server`. `HttpApiOtlp.layer` already
105
- includes this layer alongside the browser proxy routes.
115
+ ### Browser API
106
116
 
107
- ```ts
117
+ All methods return Effects. Use `yield*` inside Effect code or
118
+ `Effect.runPromise(...)` / `Effect.runFork(...)` from application callbacks.
119
+
120
+ | Method | Behavior |
121
+ | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
122
+ | `identify({ userId?, organizationId? })` | Replace identity for future events; omitted fields clear old values. Emits no event. |
123
+ | `identify(null)` | Clear identity, for example on logout. |
124
+ | `track(name, properties?, options?)` | Record a named event. |
125
+ | `page(options?)` | Record `browser.page_view`. Accepts `path`, `name`, `category`, `properties`, and event `options`. `pageView` is an alias. |
126
+
127
+ `identify` has no typed failure: invalid input warns without including supplied
128
+ values and leaves identity unchanged. `track` and `page` fail with an Effect
129
+ schema error on invalid input. Identity is in memory only, applies to events
130
+ rather than automatic traces/logs, and never rewrites queued events.
131
+
132
+ ### Auth example
133
+
134
+ Mount this once under the application's Atom registry. `ApiClient` and
135
+ `authSessionAtom` are application-owned; the telemetry package has no auth
136
+ dependency. The session atom in this example exposes KrakStack Auth session data.
137
+
138
+ ```tsx
139
+ import { useAtomSubscribe, useAtomValue } from "@effect/atom-react";
140
+ import { BrowserOtlp } from "@krak-stack/registry/opentelemetry/browser";
108
141
  import { Effect } from "effect";
109
- import { ServerOtlp } from "@krak-stack/registry/opentelemetry/server";
142
+ import { AsyncResult } from "effect/reactivity";
143
+ import { ApiClient } from "@/lib/api-client";
144
+ import { authSessionAtom } from "@/services/auth/client";
145
+
146
+ export const AuthTelemetry = () => {
147
+ const runtime = useAtomValue(ApiClient.runtime);
148
+
149
+ useAtomSubscribe(
150
+ authSessionAtom,
151
+ (session) => {
152
+ if (!AsyncResult.isSuccess(runtime)) return;
153
+
154
+ Effect.runFork(
155
+ BrowserOtlp.identify(
156
+ AsyncResult.isSuccess(session) && !session.waiting && session.value
157
+ ? {
158
+ userId: session.value.user.id,
159
+ organizationId:
160
+ session.value.session.activeOrganizationId ?? undefined,
161
+ }
162
+ : null,
163
+ ),
164
+ );
165
+ },
166
+ { immediate: true },
167
+ );
110
168
 
111
- const program = ServerOtlp.track("app.order.completed", {
112
- "order.id": "order-123",
113
- }).pipe(Effect.provide(ServerOtlp.layer));
169
+ return null;
170
+ };
114
171
  ```
115
172
 
116
- Enable server events with `OTEL_LOGS_EXPORTER=otlp`, `OTEL_SERVICE_NAME`, and
117
- `OTEL_EXPORTER_OTLP_ENDPOINT` (the exporter appends `/v1/logs`), or an explicit
118
- `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`. Signal-specific headers override
119
- `OTEL_EXPORTER_OTLP_HEADERS`; `OTEL_SDK_DISABLED=true` disables export. Use a
120
- long-lived application runtime to retain batching; dispose it on shutdown to
121
- flush pending events.
173
+ This identifies after startup and clears identity during auth loading, failure,
174
+ and logout. The first page view may be anonymous. For other auth libraries, pass
175
+ the same two IDs or `null` when auth state changes. Apply your own consent policy;
176
+ do not send names, emails, or session tokens as identity.
122
177
 
123
- Browser events are separately opt-in and do not enable application log export:
178
+ ### Page views and browser options
124
179
 
125
- ```ts
126
- BrowserOtlp.layer({ serviceName: "my-app-web", events: {} });
127
-
128
- // Effects use the active BrowserOtlp.layer, even from a different calling runtime.
129
- const telemetry = Effect.gen(function* () {
130
- yield* BrowserOtlp.track("app.checkout.started", {
131
- "checkout.source": "cart",
132
- });
133
- yield* BrowserOtlp.page({
134
- name: "Documentation",
135
- category: "Docs",
136
- path: "/docs",
137
- });
138
- });
139
- ```
180
+ `events: {}` enables custom events and one page view on startup, then on pathname
181
+ changes through `pushState`, `replaceState`, and back/forward navigation.
182
+ Same-path and query/hash-only changes are ignored. Tracking follows URL changes,
183
+ not loader completion. Paths exclude query strings/fragments but may still
184
+ contain personal IDs.
140
185
 
141
- With `events: {}`, page views are automatic: one when the layer starts, then one
142
- for each pathname change through `pushState`, `replaceState`, or `popstate`
143
- (back/forward). Repeated same-path changes and query/hash-only changes are ignored.
144
- History hooks and listeners are scoped and restored on disposal. Tracking follows
145
- URL changes, not framework loader completion. The first page may be anonymous if
146
- identity has not been set yet; identify does not retroactively change it.
186
+ For sanitized route templates or custom timing, use
187
+ `events: { pageViews: false }` and call `page({ path: "/orders/:id" })` manually.
188
+ Do not combine automatic and manual tracking for the same view.
147
189
 
148
- Set `events: { pageViews: false }` to disable automatic tracking while retaining custom events.
149
- Then call `page` (`pageView` alias) manually for route templates or application-specific
150
- navigation timing. Do not also manually emit the same automatic page view.
151
- Without `path`, it reads `location.pathname` when executed. It emits the
152
- application-defined event `browser.page_view` with required attribute `url.path`,
153
- stripping query strings and fragments. Supply sanitized paths or route templates
154
- when paths contain personal information. No cookies or visitor/session IDs are
155
- created. Only the pathname is captured; paths may still contain personal IDs.
190
+ | Layer option | Default |
191
+ | ----------------------------------------- | --------------------------------------------------------------- |
192
+ | `serviceName` | Required |
193
+ | `traces` | `{}`; includes global exception capture. `false` disables both. |
194
+ | `events`, `logs`, `metrics` | `false`; enable each independently with `{}`. |
195
+ | `baseUrl` | `/api/otel` |
196
+ | `serviceVersion`, `attributes`, `headers` | Optional resource/transport metadata. |
156
197
 
157
- ### Browser identity
198
+ Browser events batch every 30 seconds, up to 100 records by default. Override
199
+ `exportInterval`, `maxBatchSize`, and `shutdownTimeout` under `events`.
158
200
 
159
- Call `BrowserOtlp.identify` when auth state becomes available or changes, and
160
- `BrowserOtlp.identify(null)` on logout. These remain Effects, but the caller does not need
161
- the browser exporter's services in its own runtime:
201
+ ### Server events and shared options
202
+
203
+ Define server events as Effects and run them inside the runtime with
204
+ `ServerOtlp.layer` (or the HTTP layer):
162
205
 
163
206
  ```ts
164
- const telemetry = Effect.gen(function* () {
165
- yield* BrowserOtlp.identify({
166
- userId: "user-123",
167
- organizationId: "org-123",
168
- });
169
- yield* BrowserOtlp.track("app.checkout.started");
170
- yield* BrowserOtlp.page({ path: "/checkout" });
171
- yield* BrowserOtlp.identify(null);
207
+ import { Effect } from "effect";
208
+ import { ServerOtlp } from "@krak-stack/registry/opentelemetry/server";
209
+
210
+ const orderCompleted = Effect.gen(function* () {
211
+ yield* ServerOtlp.track("app.order.completed", { "order.total": 49 });
172
212
  });
173
213
  ```
174
214
 
175
- Identity is in memory per telemetry runtime, not cookies or local storage.
176
- `identify` is best-effort and has no typed failure: invalid identity leaves the
177
- previous identity unchanged and logs a warning without including supplied values.
178
- `identify` replaces the complete identity; omitting an organization clears the
179
- previous organization. It emits no event. Identity is copied into each future
180
- event when recorded; changes and resets do not rewrite queued events. Identified
181
- user/org attributes override per-call properties/options, while scoped log
182
- annotations take precedence over identified identity. This applies only to event
183
- telemetry, not automatic trace/log exporters, API request headers, or authorization.
184
- Browser identity is client-supplied and untrusted; use trusted server events for
185
- billing, authorization, audit trails, or tenant-isolated reporting. Re-identify
186
- after a reload and update identity before recording events after an auth or
187
- organization change. The OTLP proxy remains passthrough and never enriches identity.
188
-
189
- Initialize the browser layer once on the application's long-lived runtime. After
190
- it starts, `Effect.runPromise(BrowserOtlp.identify(...))` and
191
- `Effect.runPromise(BrowserOtlp.track(...))` work from ordinary application code.
192
- Event methods retain typed validation errors and the calling fiber's trace/log
193
- context; `identify` handles validation failures internally.
194
- Calls executed before startup or after disposal are no-ops; nothing is buffered.
195
- If several browser layers are active, calls target the most recently started one;
196
- use a single browser layer in normal applications. There is no analytics bridge,
197
- React hook, or automatic identification.
198
-
199
- ### Event options
200
-
201
- Both environments accept
202
- `track(name, properties?, options?)`. Common options are explicit and per-call,
203
- so server requests never share mutable visitor state:
215
+ Authenticated handlers inherit `user.id` and `organization.id` from
216
+ `AuthMiddleware` log annotations. Server identity is fiber-scoped; there is no
217
+ server `identify` method. Background jobs can supply identity per event.
204
218
 
205
- ```ts
206
- const telemetry = Effect.gen(function* () {
207
- yield* ServerOtlp.track(
208
- "app.order.completed",
209
- { "order.total": 49 },
210
- {
211
- sessionId: "session-123",
212
- messageId: "order-123-completed",
213
- context: { "organization.id": "org-123", "app.locale": "en" },
214
- },
215
- );
216
- });
217
- ```
219
+ Both `track` methods accept `options`:
220
+
221
+ | Option | OTLP attribute / meaning |
222
+ | ------------------------------------------------- | ------------------------------------------------------------------- |
223
+ | `userId`, `anonymousId`, `sessionId`, `messageId` | `user.id`, `analytics.anonymous_id`, `session.id`, `log.record.uid` |
224
+ | `context` | Additional flat attributes |
225
+ | `timestamp` | Effect `DateTime.Utc` occurrence time; otherwise recorded now |
226
+
227
+ Attribute precedence, lowest to highest: context, properties, explicit identity
228
+ options, browser identified identity, scoped log annotations. Values support
229
+ strings, finite numbers, booleans, and homogeneous arrays, not nested objects.
230
+ Use stable event names and put dynamic values in attributes. Message IDs support
231
+ correlation, not guaranteed deduplication.
232
+
233
+ Events are OTLP log records with `eventName`, INFO severity, and active trace/span
234
+ IDs when available; they do not create spans. `browser.page_view`, `url.path`,
235
+ `analytics.page.name`, and `analytics.page.category` describe page events; the
236
+ analytics names are project conventions, not standardized OTel semantics.
237
+
238
+ Configure collector/storage separately. Browser identity is untrusted analytics
239
+ metadata, not authorization or an audit trail. No visitor/session IDs or cookies
240
+ are generated. Browser flushing on hidden/pagehide is best-effort. Apply payload
241
+ and rate limits at ingestion, and keep sensitive data out of events and
242
+ high-cardinality fields out of Loki labels.
218
243
 
219
- `context` and event properties become flat OTLP attributes; properties override
220
- context on collision. Options `userId`, `anonymousId`, `sessionId`, and `messageId`
221
- map to `user.id`, `analytics.anonymous_id`, `session.id`, and `log.record.uid`,
222
- overriding properties with the same keys. Scoped `Effect.annotateLogs` annotations
223
- are inherited automatically and take precedence over all per-call attributes.
224
- In authenticated server handlers, `AuthMiddleware` already supplies `user.id` and
225
- `organization.id`, so do not repeat them in `.track()` calls. Background jobs and
226
- browser code can provide identity explicitly when needed. Annotations remain
227
- fiber-scoped; no identity state is persisted by the event service.
228
- Identifiers are optional; callers own
229
- consent and identity lifecycle. Message IDs aid correlation, not guaranteed
230
- deduplication. Optional `timestamp` accepts an Effect `DateTime.Utc` for delayed
231
- events; the SDK still sets observed time to the time of recording. There is no
232
- clock-skew correction. `page` accepts `properties` and these same `options`, plus
233
- optional `name` and `category` mapped to application-defined
234
- `analytics.page.name` and `analytics.page.category` attributes. It always owns
235
- the sanitized `url.path`. The `analytics.*` fields and `browser.page_view` name
236
- are project conventions, not standardized OpenTelemetry analytics semantics.
237
- Group, Alias, profile storage, destination routing, and automatic
238
- collection of IPs, user agents, page titles, referrers, and full URLs are not
239
- implemented.
240
-
241
- Both `.track(name, attributes?)` methods follow the
242
- [OpenTelemetry event conventions](https://opentelemetry.io/docs/specs/semconv/general/events/):
243
- records have the native `eventName` field, an occurrence timestamp, INFO severity
244
- number (9), flat structured attributes, and no body. The SDK sets observed time
245
- when it records the occurrence. Events inherit active trace/span IDs without
246
- creating spans. Use stable domain-qualified names with no dynamic identifiers;
247
- put changing values in attributes. Document each custom event's trigger and
248
- required/optional attributes; include `error.type` for failures. These conventions
249
- are still in development. Attribute values support strings, finite numbers,
250
- booleans, and homogeneous arrays of those values. Invalid inputs fail with an
251
- Effect schema error.
252
-
253
- The logs proxy must be enabled with `OTEL_LOGS_EXPORTER=otlp` for browser events.
254
- OTLP transports events; configure a collector and a logs backend such as Loki for
255
- storage and Grafana dashboards. Browser flushing on hidden/pagehide is best
256
- effort. Apply payload limits and rate limits at your public ingestion boundary,
257
- avoid sensitive attributes, and keep high-cardinality fields out of Loki labels.
244
+ ## Other services
258
245
 
259
246
  `@krak-stack/registry/service-notification` is the source-compatible direct
260
247
  dispatcher. Use the separate `@krak-stack/notifications` package for a durable
@@ -1339,9 +1339,7 @@ var uiFromState = (state) => ({
1339
1339
  var sameUiState = (left, right) => left.columnVisibility === right.columnVisibility && left.columnSizing === right.columnSizing && left.rowSelection === right.rowSelection && left.grouping === right.grouping && left.collapsedGroups === right.collapsedGroups && left.view === right.view;
1340
1340
  var sameQueryState = (left, right) => left.page === right.page && left.pageSize === right.pageSize && left.globalFilter === right.globalFilter && left.sort === right.sort;
1341
1341
  var initialPublicState = (props, uiState) => ({
1342
- ...DEFAULT_QUERY,
1343
- ...props.initialState,
1344
- ...props.state,
1342
+ ...queryFromState(props.state ?? { ...DEFAULT_QUERY, ...props.initialState }),
1345
1343
  ...uiState
1346
1344
  });
1347
1345
  var buildDataTableModel = (store) => {
@@ -1378,7 +1376,7 @@ var changeState = (setStore, update) => {
1378
1376
  if (!sameUiState(uiState, store.state)) {
1379
1377
  store.config.onUiStateChange(uiState);
1380
1378
  }
1381
- const state = store.controlledState ? { ...proposed, ...store.controlledState } : proposed;
1379
+ const state = store.controlledState ? { ...proposed, ...queryFromState(store.controlledState) } : proposed;
1382
1380
  if (sameDataTableState(state, store.state))
1383
1381
  return store;
1384
1382
  const next = { ...store, state };
@@ -1700,7 +1698,7 @@ var DataTableToolbar = ({
1700
1698
  }),
1701
1699
  store.state.globalFilter ? /* @__PURE__ */ jsx14(Button, {
1702
1700
  "aria-label": labels.filter,
1703
- className: "absolute top-1/2 right-1 size-7 -translate-y-1/2",
1701
+ className: "absolute top-1/2 right-1 size-7 -translate-y-1/2 active:not-aria-[haspopup]:-translate-y-1/2",
1704
1702
  onClick: () => update((state) => ({
1705
1703
  ...state,
1706
1704
  globalFilter: undefined,
@@ -2887,7 +2885,11 @@ var HydratedDataTable = ({
2887
2885
  labels: dataTableMessages(props.locale, props.messages),
2888
2886
  locale: props.locale ?? "en"
2889
2887
  };
2890
- const state = { ...store.state, ...uiState, ...props.state };
2888
+ const state = {
2889
+ ...store.state,
2890
+ ...uiState,
2891
+ ...queryFromState(props.state ?? store.state)
2892
+ };
2891
2893
  const modelChanged = store.rowData !== props.rowData || store.columnDefs !== props.columnDefs || !sameDataTableState(store.state, state) || store.config.getRowId !== config.getRowId || store.config.features.pagination !== config.features.pagination;
2892
2894
  const next = {
2893
2895
  ...store,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krak-stack/registry",
3
- "version": "0.1.41",
3
+ "version": "0.1.43",
4
4
  "description": "Tree-shakable KrakStack components and Effect services.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -11,7 +11,6 @@
11
11
  "files": [
12
12
  "dist",
13
13
  "README.md",
14
- "patches",
15
14
  "tailwind.css"
16
15
  ],
17
16
  "type": "module",
@@ -241,8 +240,8 @@
241
240
  "@effect/platform-browser": "^4.0.0",
242
241
  "@iconify/react": "^6.0.2",
243
242
  "@inlang/paraglide-js": "^2.19.0",
244
- "@lucas-barake/effect-form": "0.25.0-beta.6",
245
- "@lucas-barake/effect-form-react": "0.26.0-beta.5",
243
+ "@lucas-barake/effect-form": "1.1.0",
244
+ "@lucas-barake/effect-form-react": "1.1.0",
246
245
  "@tanstack/highlight": "^0.0.10",
247
246
  "@tanstack/react-form": "^1.33.0",
248
247
  "@tanstack/react-router": "^1.170.15",
@@ -1,66 +0,0 @@
1
- diff --git a/dist/FormReact.d.ts b/dist/FormReact.d.ts
2
- index 61b65ad3ef858a3d9994d4cfde7e47216d44b549..0431a57a4a27eefa43180fc19f04f887a25ebf24 100644
3
- --- a/dist/FormReact.d.ts
4
- +++ b/dist/FormReact.d.ts
5
- @@ -4,8 +4,8 @@ import type * as FormBuilder from "@lucas-barake/effect-form/FormBuilder";
6
- import type * as Effect from "effect/Effect";
7
- import * as Option from "effect/Option";
8
- import type * as Schema from "effect/Schema";
9
- -import * as Atom from "effect/unstable/reactivity/Atom";
10
- -import type * as AtomRegistry from "effect/unstable/reactivity/AtomRegistry";
11
- +import * as Atom from "effect/reactivity/Atom";
12
- +import type * as AtomRegistry from "effect/reactivity/AtomRegistry";
13
- import * as React from "react";
14
- export type FieldValue<T> = FieldStateModule.FieldValue<T>;
15
- export type FieldState<E> = FieldStateModule.FieldState<E>;
16
- diff --git a/dist/FormReact.js b/dist/FormReact.js
17
- index 03e34ec60b833b4dd220ac6faffe70b9138703cd..f313c18c5e6cdb7138e19180aeb0acd4281857fa 100644
18
- --- a/dist/FormReact.js
19
- +++ b/dist/FormReact.js
20
- @@ -4,7 +4,7 @@ import { Field, FormAtoms } from "@lucas-barake/effect-form";
21
- import { getNestedValue } from "@lucas-barake/effect-form/Path";
22
- import * as Layer from "effect/Layer";
23
- import * as Option from "effect/Option";
24
- -import * as Atom from "effect/unstable/reactivity/Atom";
25
- +import * as Atom from "effect/reactivity/Atom";
26
- import * as React from "react";
27
- import { createContext, useContext } from "react";
28
- const ArrayItemContext = /*#__PURE__*/createContext(null);
29
- diff --git a/package.json b/package.json
30
- index 416aed4983dfb7dfc1528b3cca636b860ab0986e..048e49b01201623854c1c8f042044d3f5bd64703 100644
31
- --- a/package.json
32
- +++ b/package.json
33
- @@ -41,14 +41,14 @@
34
- "@lucas-barake/effect-form": "^0.25.0-beta.6"
35
- },
36
- "devDependencies": {
37
- - "@effect/atom-react": "4.0.0-beta.52",
38
- + "@effect/atom-react": "4.0.0",
39
- "@vitejs/plugin-react": "^5.1.1",
40
- - "effect": "4.0.0-beta.52",
41
- + "effect": "4.0.0",
42
- "react": "^19.0.0"
43
- },
44
- "peerDependencies": {
45
- - "@effect/atom-react": ">=4.0.0-beta.52 <4.0.1",
46
- - "effect": ">=4.0.0-beta.52 <4.0.1",
47
- + "@effect/atom-react": "^4.0.0",
48
- + "effect": "^4.0.0",
49
- "react": "^19.0.0"
50
- },
51
- "scripts": {
52
- diff --git a/src/FormReact.tsx b/src/FormReact.tsx
53
- index 49c358e92fe04a62a9ef97dbae6665ce53e905a5..dfb2792d4b824d448bf3e8f4b469c0861422bd6f 100644
54
- --- a/src/FormReact.tsx
55
- +++ b/src/FormReact.tsx
56
- @@ -7,8 +7,8 @@ import type * as Effect from "effect/Effect"
57
- import * as Layer from "effect/Layer"
58
- import * as Option from "effect/Option"
59
- import type * as Schema from "effect/Schema"
60
- -import * as Atom from "effect/unstable/reactivity/Atom"
61
- -import type * as AtomRegistry from "effect/unstable/reactivity/AtomRegistry"
62
- +import * as Atom from "effect/reactivity/Atom"
63
- +import type * as AtomRegistry from "effect/reactivity/AtomRegistry"
64
- import * as React from "react"
65
- import { createContext, useContext } from "react"
66
-
@@ -1,86 +0,0 @@
1
- diff --git a/dist/FormAtoms.d.ts b/dist/FormAtoms.d.ts
2
- index 08d1e4e2e8edf08cecb5b550099c3293cbd10cd7..f7b1fa4a5a7d65e8b8b3785dc9eb5397d24718b4 100644
3
- --- a/dist/FormAtoms.d.ts
4
- +++ b/dist/FormAtoms.d.ts
5
- @@ -1,7 +1,7 @@
6
- import * as Effect from "effect/Effect";
7
- import * as Option from "effect/Option";
8
- import * as Schema from "effect/Schema";
9
- -import * as Atom from "effect/unstable/reactivity/Atom";
10
- +import * as Atom from "effect/reactivity/Atom";
11
- import * as Field from "./Field.ts";
12
- import * as FormBuilder from "./FormBuilder.ts";
13
- import * as Mode from "./Mode.ts";
14
- diff --git a/dist/FormAtoms.js b/dist/FormAtoms.js
15
- index 663c4478a08eb17bfb7a11df952ced8f7812cbf8..ebaa1be93c33af0390857e945a9d414094f215ab 100644
16
- --- a/dist/FormAtoms.js
17
- +++ b/dist/FormAtoms.js
18
- @@ -3,8 +3,8 @@ import * as Effect from "effect/Effect";
19
- import { pipe } from "effect/Function";
20
- import * as Option from "effect/Option";
21
- import * as Schema from "effect/Schema";
22
- -import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
23
- -import * as Atom from "effect/unstable/reactivity/Atom";
24
- +import * as AsyncResult from "effect/reactivity/AsyncResult";
25
- +import * as Atom from "effect/reactivity/Atom";
26
- import * as Field from "./Field.js";
27
- import * as FormBuilder from "./FormBuilder.js";
28
- import { recalculateDirtyFieldsForArray, recalculateDirtySubtree } from "./internal/dirty.js";
29
- diff --git a/dist/FormBuilder.d.ts b/dist/FormBuilder.d.ts
30
- index d42cf00d24b9efea5168831549b85468a64dfcef..16dfc1af6443555454ec7e6219c94eeabce3d724 100644
31
- --- a/dist/FormBuilder.d.ts
32
- +++ b/dist/FormBuilder.d.ts
33
- @@ -1,7 +1,7 @@
34
- import type * as Effect from "effect/Effect";
35
- import type * as Option from "effect/Option";
36
- import * as Schema from "effect/Schema";
37
- -import type * as AtomRegistry from "effect/unstable/reactivity/AtomRegistry";
38
- +import type * as AtomRegistry from "effect/reactivity/AtomRegistry";
39
- import type { ArrayFieldDef, DecodedFromFields, EncodedFromFields, FieldDef, FieldsRecord } from "./Field.ts";
40
- /**
41
- * Flattens an intersection of field records into a single object type so that
42
- diff --git a/package.json b/package.json
43
- index 96ad0aa1729c64e8378a8cb2ad29f13b5347e568..06ae5ac6312779be749ff867b846c8f3c4ccf5b1 100644
44
- --- a/package.json
45
- +++ b/package.json
46
- @@ -36,10 +36,10 @@
47
- "license": "MIT",
48
- "sideEffects": [],
49
- "peerDependencies": {
50
- - "effect": ">=4.0.0-beta.52 <4.0.1"
51
- + "effect": "^4.0.0"
52
- },
53
- "devDependencies": {
54
- - "effect": "4.0.0-beta.52"
55
- + "effect": "4.0.0"
56
- },
57
- "scripts": {
58
- "build": "tsc -b tsconfig.json && pnpm babel",
59
- diff --git a/src/FormAtoms.ts b/src/FormAtoms.ts
60
- index bc60a7f7b676edf4d1e99f6eb4162335b3247022..60d3dadfe2ef14c0a1b66b5e16886e8870c82681 100644
61
- --- a/src/FormAtoms.ts
62
- +++ b/src/FormAtoms.ts
63
- @@ -3,8 +3,8 @@ import * as Effect from "effect/Effect"
64
- import { pipe } from "effect/Function"
65
- import * as Option from "effect/Option"
66
- import * as Schema from "effect/Schema"
67
- -import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"
68
- -import * as Atom from "effect/unstable/reactivity/Atom"
69
- +import * as AsyncResult from "effect/reactivity/AsyncResult"
70
- +import * as Atom from "effect/reactivity/Atom"
71
- import * as Field from "./Field.ts"
72
- import * as FormBuilder from "./FormBuilder.ts"
73
- import { recalculateDirtyFieldsForArray, recalculateDirtySubtree } from "./internal/dirty.ts"
74
- diff --git a/src/FormBuilder.ts b/src/FormBuilder.ts
75
- index 764de854be6b072967d1140c707ba9565eda9516..6a2d0fe285ae3b2d1afc4bf928897e5b7bfb0a4b 100644
76
- --- a/src/FormBuilder.ts
77
- +++ b/src/FormBuilder.ts
78
- @@ -3,7 +3,7 @@ import type * as Option from "effect/Option"
79
- import * as Predicate from "effect/Predicate"
80
- import * as Schema from "effect/Schema"
81
- import * as SchemaGetter from "effect/SchemaGetter"
82
- -import type * as AtomRegistry from "effect/unstable/reactivity/AtomRegistry"
83
- +import type * as AtomRegistry from "effect/reactivity/AtomRegistry"
84
-
85
- import type {
86
- AnyFieldDef,
package/patches/README.md DELETED
@@ -1,31 +0,0 @@
1
- # Temporary Effect form compatibility patches
2
-
3
- These patches backport the stable Effect 4 changes from upstream commit
4
- [`c10a53e041c9b0b338b26b2af66be5eb24f07d47`](https://github.com/lucas-barake/effect-form/commit/c10a53e041c9b0b338b26b2af66be5eb24f07d47).
5
- The fixed npm packages are awaiting [release PR #111](https://github.com/lucas-barake/effect-form/pull/111).
6
-
7
- The patches update reactivity imports in shipped JavaScript, TypeScript
8
- declarations, and source, and change Effect peer ranges to `^4.0.0`.
9
- They do not change form behavior or package versions.
10
-
11
- ## Installation
12
-
13
- The workspace-root `package.json` configures `patchedDependencies` and exact
14
- version overrides for both packages. Run `bun install` to apply them; commit
15
- these patch files, `package.json`, and `bun.lock` together. In a monorepo, configure
16
- the patches at the workspace root, not inside individual packages.
17
-
18
- Patches do **not** propagate from a published KrakStack package to a consuming
19
- application. Every application using the affected form packages must configure
20
- both patches itself. The interim Auth and Registry packages also ship copies
21
- under `patches/` for consumers to copy into their application roots.
22
-
23
- ## Removing the workaround
24
-
25
- After upstream publishes `@lucas-barake/effect-form@0.25.0-beta.7` and
26
- `@lucas-barake/effect-form-react@0.26.0-beta.6` (or newer compatible releases):
27
-
28
- 1. Update direct dependencies and KrakStack peer requirements to the fixed versions.
29
- 2. Remove the two form overrides and `patchedDependencies` entries.
30
- 3. Remove these two patch files and any copies shipped with KrakStack packages.
31
- 4. Run `bun install`, then the project's type, test, and release checks.