effer 0.0.1

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 ADDED
@@ -0,0 +1,274 @@
1
+ # Effer
2
+
3
+ An Effect native UI library based on lit-html.
4
+
5
+ ## Installation
6
+
7
+ WIP.
8
+
9
+ ## Creating a Counter with Effer
10
+
11
+ Example:
12
+
13
+ ```ts
14
+ // INSIDE counter.ts
15
+
16
+ import { Data, Effect } from "effect";
17
+ import { Effer, html, makeReducer } from "effer";
18
+
19
+ type Msg = Data.TaggedEnum<{
20
+ Increment: {};
21
+ Decrement: {};
22
+ }>
23
+ const { Increment, Decrement, $match } = Data.taggedEnum<Msg>()
24
+
25
+ const makeCounterState = makeReducer(
26
+ 0,
27
+ (state: number, msg: Msg) => $match({
28
+ Increment: () => Effect.succeed(state + 1),
29
+ Decrement: () => Effect.succeed(state - 1),
30
+ })(msg)
31
+ )
32
+
33
+ export class CounterService extends Effect.Service<CounterService>()('CounterService', {
34
+ effect: makeCounterState
35
+ }) {}
36
+
37
+ const _Counter = () => Effect.gen(function*() {
38
+ const { attach, queueMsg } = yield* Effer
39
+ const [counterStream, counterQueue] = yield* CounterService
40
+
41
+ return html`
42
+ <section class="counter-container d-flex flex-row align-items-baseline justify-content-center">
43
+ <button
44
+ class="btn btn-primary btn-sm counter-button"
45
+ id="decButton"
46
+ @click=${queueMsg(counterQueue, () => Increment())}
47
+ >
48
+ - 1
49
+ </button>
50
+ Count is ${yield* attach(counterStream)}
51
+ <button
52
+ class="btn btn-primary btn-sm counter-button"
53
+ id="incButton"
54
+ @click=${queueMsg(counterQueue, () => Decrement())}
55
+ >
56
+ + 1
57
+ </button>
58
+ </section>
59
+ `
60
+ })
61
+
62
+ // Optional - make your component a service for ease of dependency management and mocking
63
+
64
+ export class Counter extends Effect.Service<Counter>()('Counter', {
65
+ effect: _Counter(),
66
+ dependencies: [CounterService.Default, Effer.Default]
67
+ }) {}
68
+
69
+ // INSIDE main.ts
70
+
71
+ const ComponentsLayer = Layer.empty.pipe(
72
+ Layer.merge(Counter.Default),
73
+ // ... merge in any other component layers
74
+ )
75
+
76
+ App().pipe(
77
+ Effect.andThen(
78
+ // render our component to the DOM element with ID 'app'
79
+ app => render(app, document.getElementById('app')!)
80
+ ),
81
+ Layer.effectDiscard, // transform the render effect into a Layer
82
+ Layer.provide(ComponentsLayer), // merge in Component layers
83
+ Layer.provideMerge(layer), // merge in Effer layer
84
+ Layer.launch, // launch our combined Effer app layer
85
+ BrowserRuntime.runMain
86
+ )
87
+ ```
88
+
89
+
90
+ To bring our UI and business logic together, Effer gives us two tools: attach and queueMsg, both available in the Effer service.
91
+
92
+ ```ts
93
+ const { attach, queueMsg } = yield* Effer
94
+ ```
95
+
96
+ In the UI, we need to represent data changing over time. Effect gives us Streams as a way to do that. The attach method of the Effer service lets you "attach" a stream (or anything that can be converted to a Stream) to the UI, and the UI will automatically display the most up-to-date value of that Stream.
97
+
98
+ ```ts
99
+ html`
100
+ Count is ${yield* attach(counterStream)}
101
+ `
102
+ ```
103
+
104
+ Here is a complete list of what can be attached:
105
+
106
+ ```ts
107
+ type Attachable<A,E,R> =
108
+ | Effect<A,E,R>
109
+ | SubscriptionRef<A>
110
+ | PubSub<A>
111
+ | Queue<A>
112
+ | Stream<A,E,R>
113
+ | Channel<Chunk.Chunk<A>, unknown, E, unknown, unknown, unknown, R>
114
+ ```
115
+
116
+ When we need to handle events from the UI, we do so with the queueMsg method of the Effer service. This function can go anywhere an event listener callback is expected (like onclick, onchange, etc.). It takes a queue to send the event to, and a function that maps from the DOM event to the queue's event that we want to dispatch:
117
+
118
+ ```ts
119
+ html`
120
+ <button
121
+ class="btn btn-primary btn-sm counter-button"
122
+ id="decButton"
123
+ @click=${queueMsg(counterQueue, (e: MouseEvent) => Increment())}
124
+ >
125
+ `
126
+ ```
127
+
128
+ ## Managing State
129
+
130
+ ### makeReducer - For Complex State or Logic
131
+
132
+ To manage state, Effer provides two helper functions: makeReducer and makeState. These are very similar to useReducer and useState in React, except you use them outside your UI components as part of your business logic.
133
+
134
+ makeReducer lets you define a state and update it using events:
135
+
136
+ ```ts
137
+ type Msg = Data.TaggedEnum<{
138
+ Increment: {};
139
+ Decrement: {};
140
+ }>
141
+ const { Increment, Decrement, $match } = Data.taggedEnum<Msg>()
142
+
143
+ const makeCounterState = makeReducer(
144
+ 0,
145
+ (state: number, msg: Msg) => $match({
146
+ Increment: () => Effect.succeed(state + 1),
147
+ Decrement: () => Effect.succeed(state - 1),
148
+ })(msg)
149
+ )
150
+
151
+ // Making our state values a Service so we can easily pass it around
152
+ export class CounterService extends Effect.Service<CounterService>()('CounterService', {
153
+ effect: makeCounterState
154
+ }) {}
155
+ ```
156
+
157
+ We define the expected update messages as Increment and Decrement, and we provide a function that takes the old state and a message, and provides a new updated state. Now when we inject the service, we will get the stream of values as well as a queue to send updates to:
158
+
159
+ ```ts
160
+ // counterQueue will accept either Increment or Decrement and the stream will update
161
+ // according to the update function
162
+ const [counterStream, counterQueue] = yield* CounterService
163
+ ```
164
+
165
+ ### makeState - For Simple State Management
166
+
167
+ makeState is very similar, but more simplified. We just provide an initial state, and the queue will accept new state values instead of messages.
168
+
169
+ ```ts
170
+ const makeCounterState = makeState(0)
171
+
172
+ // Making our state values a Service so we can easily pass it around
173
+ export class CounterService extends Effect.Service<CounterService>()('CounterService', {
174
+ effect: makeCounterState
175
+ }) {}
176
+ ```
177
+
178
+ ```ts
179
+ // the counterQueue now accepts a number (the new count) instead of update messages
180
+ const [counterStream, counterQueue] = yield* CounterService
181
+ ```
182
+
183
+ ### makeAsyncResult - For Async State and Logic
184
+
185
+ If we have an effect that as asynchronous, like making an HTTP call, we can wrap that effect in makeAsyncResult:
186
+
187
+ ```ts
188
+ const posts = yield* makeAsyncResult(getPostsAsyncEffect) // an async effect wrapped in makeAsyncResult
189
+ ```
190
+
191
+ When you wrap an `Effect<A,E,R>` in makeAsyncResult, you get 3 things. The first is a `Stream<Result<A,E>, never, R>` where `Result<A,E>` is:
192
+
193
+ ```ts
194
+ export type Result<A,E> = Data.TaggedEnum<{
195
+ Loading: {}
196
+ Success: { readonly data: A }
197
+ Failure: { readonly error: E }
198
+ }> & {}
199
+ ```
200
+
201
+ The other thing makeAsyncResult gives us is a helper function called `match()` for matching the state of the streaming Result values:
202
+
203
+ ```ts
204
+ const posts = yield* makeAsyncResult(getPostsAsyncEffect) // an async effect wrapped in makeAsyncResult
205
+ // mapping the state of our Result to what we want to display on screen
206
+ const postsTable = posts.stream.pipe(
207
+ Stream.map(postsClient.match({
208
+ Loading: () => html`<h1>Loading...</h1>`, // if the async effect is still loading, show this
209
+ Success: ({ data }) => data.map(post => PostCard(post)), // if it loaded successfully, show the PostCard component
210
+ Failure: ({ error }) => html`<p>Error retrieving data: ${error}</p>` // if it errored out, show this
211
+ }))
212
+ )
213
+ ```
214
+
215
+ Note that since `Result<A,E>` is a TaggedEnum, `match()` is exactly the same as the `$match()` function you get from creating a TaggedEnum. See the [Effect Documentation](https://effect.website/docs/data-types/data/#union-of-tagged-structs)
216
+
217
+ ## Navigation and URLs
218
+
219
+ Effer offers a NavService for handling things related to navigation and URLs. Here is its interface:
220
+
221
+ ```ts
222
+ interface NavService {
223
+ url: Ref.Ref<URL>; // the current URL as a Ref
224
+ pathStream: Stream.Stream<URL>; // a stream of the current URL value for reacting to changes
225
+ getQueryParam: (name: string) => Effect.Effect<string, NoSuchElementException, never> // helper to get a query param from the URL
226
+ navigate: typeof window.navigation.navigate; // the window's navigate() method
227
+ }
228
+ ```
229
+
230
+ You can use this inside of an Effect (like an Effer component) to navigate like so:
231
+
232
+ ```ts
233
+ export const App = () => Effect.gen(function*() {
234
+ const { pathStream } = yield* NavService // get the pathStream from NavService
235
+ const { attach } = yield* Effer
236
+ // a function that maps from a path string to the Effer component we want to display
237
+ const navFn = (path: string) => {
238
+ switch (path) {
239
+ case '/counters':
240
+ return yield* Counter
241
+ case '/todos':
242
+ return yield* Todos
243
+ case '/posts':
244
+ return yield* Posts
245
+ default:
246
+ return yield* Todos
247
+ }
248
+ }
249
+
250
+ // getting the pathname from the pathStream then running that through our nav function
251
+ const page = pathStream.pipe(
252
+ Stream.map(url => url.pathname),
253
+ Stream.map(navFn)
254
+ )
255
+ // attaching the page stream to the template so the current page displays
256
+ return html`
257
+ <main class="w-100">
258
+ ${ yield* attach(page) }
259
+ </main>
260
+ `
261
+ })
262
+ ```
263
+
264
+ You can also use NavService to retrieve query params from the current URL:
265
+
266
+ ```ts
267
+ const {getQueryParam} = yield* NavService
268
+ // Getting a "count" query param and parsing it into an integer
269
+ const startingCount: number = yield* getQueryParam('count').pipe(
270
+ Effect.map(parseInt),
271
+ Effect.orElseSucceed(() => 0)
272
+ )
273
+ ```
274
+
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.render = exports.makeState = exports.makeReducer = exports.makeAsyncResult = exports.layer = exports.html = exports.NavService = exports.Effer = exports.AsyncReplaceDirective = void 0;
7
+ var _effect = require("effect");
8
+ var _Cause = require("effect/Cause");
9
+ var _Channel = require("effect/Channel");
10
+ var _Effect = require("effect/Effect");
11
+ var _Predicate = require("effect/Predicate");
12
+ var _Stream = require("effect/Stream");
13
+ var _litHtml = require("lit-html");
14
+ var _asyncReplace = require("lit-html/directives/async-replace.js");
15
+ var Nav = _interopRequireWildcard(require("@typed/navigation"));
16
+ var _id = require("@typed/id");
17
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
18
+ /**
19
+ * Create an HTML template result that can be rendered to the DOM
20
+ */
21
+ const html = exports.html = _litHtml.html;
22
+ /**
23
+ * Renders a template result to the container
24
+ */
25
+ const render = exports.render = _litHtml.render;
26
+ class AsyncReplaceDirective extends _asyncReplace.AsyncReplaceDirective {}
27
+ exports.AsyncReplaceDirective = AsyncReplaceDirective;
28
+ const isQueue = val => (0, _Predicate.hasProperty)(val, _effect.Unify.ignoreSymbol) && (0, _Predicate.hasProperty)(val[_effect.Unify.ignoreSymbol], 'Dequeue');
29
+ const isStream = val => (0, _Predicate.hasProperty)(val, _Stream.StreamTypeId);
30
+ const isSubscriptionRef = val => (0, _Predicate.hasProperty)(val, _effect.SubscriptionRef.SubscriptionRefTypeId);
31
+ /**
32
+ * The Effer service provides methods for attaching Attachable values to the template and queueing events
33
+ */
34
+ class Effer extends /*#__PURE__*/_effect.Effect.Service()('Effer', {
35
+ effect: /*#__PURE__*/_effect.Effect.gen(function* () {
36
+ const attach = val => {
37
+ let stream;
38
+ if ((0, _Channel.isChannel)(val)) {
39
+ stream = _effect.Stream.fromChannel(val);
40
+ } else if (isSubscriptionRef(val)) {
41
+ stream = val.changes;
42
+ } else if ((0, _Effect.isEffect)(val) && !isQueue(val)) {
43
+ stream = _effect.Stream.fromEffect(val);
44
+ } else if (isQueue(val)) {
45
+ stream = _effect.Stream.fromQueue(val);
46
+ } else if (isStream(val)) {
47
+ stream = val;
48
+ } else {
49
+ stream = _effect.Stream.fromPubSub(val);
50
+ }
51
+ return stream.pipe(_effect.Stream.toAsyncIterableEffect, _effect.Effect.andThen(iter => (0, _asyncReplace.asyncReplace)(iter)));
52
+ };
53
+ const queueMsg = (offer, mapper) => {
54
+ if (mapper) {
55
+ return e => offer(mapper(e));
56
+ }
57
+ return offer;
58
+ };
59
+ return {
60
+ /**
61
+ * Attaches any Attachable value to the template:
62
+ * ```ts
63
+ * const Counter = () => Effect.gen(function*() {
64
+ * [ countRef, countQueue ] = yield* CounterService // service made with makeReducer or makeState
65
+ *
66
+ * return html`
67
+ * <p>The count is ${yield* attach(countRef)}</p>
68
+ * `
69
+ * })
70
+ * ```
71
+ */
72
+ attach,
73
+ /**
74
+ * Used in place of an event handler callback, this function takes a queue to dispatch messages to,
75
+ * as well as a mapping function from the DOM event to the queue's expected event type
76
+ * ```ts
77
+ * const Counter = () => Effect.gen(function*() {
78
+ * [ countRef, countQueue ] = yield* CounterService // service made with makeReducer
79
+ *
80
+ * return html`
81
+ * <button
82
+ * @click=${queueMsg(countQueue, () => Increment())}
83
+ * > // Increment() is an action defined as part of the CounterService reducer
84
+ * The count is ${yield* attach(countRef)}
85
+ * </button>
86
+ * `
87
+ * })
88
+ * ```
89
+ */
90
+ queueMsg
91
+ };
92
+ })
93
+ // dependencies: [Registry.layer]
94
+ }) {}
95
+ /**
96
+ * Creates a stream of the latest state value, and a queue to update the value.
97
+ * @param initialState The starting state value
98
+ * @param updateFn An effectful function that takes the old state, an update message, and returns a new state
99
+ * @returns A tuple of the stream of the current state value and a queue to dispatch update messages
100
+ *
101
+ * ```ts
102
+ * type Msg = Data.TaggedEnum<{
103
+ * Increment: {};
104
+ * Decrement: {};
105
+ * }>
106
+ * const { Increment, Decrement, $match } = Data.taggedEnum<Msg>()
107
+ * const counterReducer = (state: number, msg: Msg) => $match({
108
+ * Increment: () => Effect.succeed(state + 1),
109
+ * Decrement: () => Effect.succeed(state - 1)
110
+ * })
111
+ *
112
+ * // Inside an Effect
113
+ * const [ countStream, countQueue ] = yield* makeReducer(0, counterReducer)
114
+ * ```
115
+ */
116
+ exports.Effer = Effer;
117
+ const makeReducer = (initialState, updateFn) => _effect.Effect.gen(function* () {
118
+ const subRef = yield* _effect.SubscriptionRef.make(initialState);
119
+ const updateQueue = yield* _effect.Queue.unbounded();
120
+ yield* _effect.Effect.gen(function* () {
121
+ const msg = yield* updateQueue.take;
122
+ yield* _effect.SubscriptionRef.updateEffect(subRef, state => updateFn(state, msg));
123
+ }).pipe(_effect.Effect.forever, _effect.Effect.fork);
124
+ const dispatch = msg => _effect.Queue.unsafeOffer(updateQueue, msg);
125
+ return {
126
+ stream: subRef.changes,
127
+ dispatch
128
+ };
129
+ });
130
+ exports.makeReducer = makeReducer;
131
+ const makeState = initialState => _effect.Effect.gen(function* () {
132
+ const subRef = yield* _effect.SubscriptionRef.make(initialState);
133
+ const updateQueue = yield* _effect.Queue.unbounded();
134
+ yield* _effect.Effect.gen(function* () {
135
+ const updateFn = yield* updateQueue.take;
136
+ yield* _effect.SubscriptionRef.update(subRef, updateFn);
137
+ }).pipe(_effect.Effect.forever, _effect.Effect.fork);
138
+ const set = val => _effect.Queue.unsafeOffer(updateQueue, _ => val);
139
+ const update = updateFn => _effect.Queue.unsafeOffer(updateQueue, updateFn);
140
+ return {
141
+ stream: subRef.changes,
142
+ set,
143
+ update
144
+ };
145
+ });
146
+ /**
147
+ * Effer's service to interact with navigation. Provides the current URL object, a stream of the
148
+ * current app path, a method to get a query param from the URL, and a method to navigate the page.
149
+ */
150
+ exports.makeState = makeState;
151
+ class NavService extends /*#__PURE__*/_effect.Context.Tag('NavService')() {
152
+ static Live = /*#__PURE__*/_effect.Layer.effect(NavService, /*#__PURE__*/_effect.Effect.gen(function* () {
153
+ const url = yield* _effect.Ref.make(new URL(window.navigation.currentEntry?.url));
154
+ const pathStream = _effect.Stream.fromEventListener(window.navigation, 'navigate').pipe(_effect.Stream.map(e => new URL(e.destination.url)), _effect.Stream.merge(_effect.Stream.make(new URL(window.navigation.currentEntry?.url))), _effect.Stream.tap(u => _effect.Ref.set(url, u)));
155
+ const getQueryParam = name => _effect.Effect.gen(function* () {
156
+ const result = (yield* _effect.Ref.get(url)).searchParams.get(name);
157
+ if (result === null) {
158
+ yield* _effect.Effect.fail(new _Cause.NoSuchElementException());
159
+ }
160
+ return result;
161
+ });
162
+ return {
163
+ /**
164
+ * The current URL object
165
+ */
166
+ url,
167
+ /**
168
+ * A stream of the current app path ('/', '/actuator', etc.)
169
+ */
170
+ pathStream,
171
+ /**
172
+ * Method used to navigate. Accepts a URL string and navigates the page
173
+ */
174
+ navigate: window.navigation.navigate,
175
+ /**
176
+ * Get a value from the current URL's query params
177
+ */
178
+ getQueryParam
179
+ };
180
+ }));
181
+ }
182
+ exports.NavService = NavService;
183
+ const makeAsyncResult = effect => {
184
+ const {
185
+ Loading,
186
+ Success,
187
+ Failure,
188
+ $is,
189
+ $match
190
+ } = _effect.Data.taggedEnum();
191
+ const startStream = _effect.Stream.make(Loading());
192
+ const resultStream = _effect.Stream.asyncPush(emit => _effect.Effect.gen(function* () {
193
+ const result = yield* effect.pipe(_effect.Effect.map(data => Success({
194
+ data
195
+ })), _effect.Effect.mapError(error => Failure({
196
+ error
197
+ })), _effect.Effect.merge);
198
+ emit.single(result);
199
+ }));
200
+ return {
201
+ stream: _effect.Stream.concat(startStream, resultStream),
202
+ is: $is,
203
+ match: $match
204
+ };
205
+ };
206
+ exports.makeAsyncResult = makeAsyncResult;
207
+ const layer = exports.layer = /*#__PURE__*/Effer.Default.pipe(/*#__PURE__*/_effect.Layer.provideMerge(NavService.Live), /*#__PURE__*/_effect.Layer.provide(/*#__PURE__*/Nav.fromWindow(window)), /*#__PURE__*/_effect.Layer.provide(_id.GetRandomValues.CryptoRandom));
208
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["_effect","require","_Cause","_Channel","_Effect","_Predicate","_Stream","_litHtml","_asyncReplace","Nav","_interopRequireWildcard","_id","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","html","exports","_html","render","_render","AsyncReplaceDirective","_AsyncReplaceDirective","isQueue","val","hasProperty","Unify","ignoreSymbol","isStream","StreamTypeId","isSubscriptionRef","SubscriptionRef","SubscriptionRefTypeId","Effer","Effect","Service","effect","gen","attach","stream","isChannel","Stream","fromChannel","changes","isEffect","fromEffect","fromQueue","fromPubSub","pipe","toAsyncIterableEffect","andThen","iter","asyncReplace","queueMsg","offer","mapper","makeReducer","initialState","updateFn","subRef","make","updateQueue","Queue","unbounded","msg","take","updateEffect","state","forever","fork","dispatch","unsafeOffer","makeState","update","_","NavService","Context","Tag","Live","Layer","url","Ref","URL","window","navigation","currentEntry","pathStream","fromEventListener","map","destination","merge","tap","u","getQueryParam","name","result","searchParams","fail","NoSuchElementException","navigate","makeAsyncResult","Loading","Success","Failure","$is","$match","Data","taggedEnum","startStream","resultStream","asyncPush","emit","data","mapError","error","single","concat","is","match","layer","Default","provideMerge","provide","fromWindow","GetRandomValues","CryptoRandom"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":";;;;;;AAAA,IAAAA,OAAA,GAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,QAAA,GAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AACA,IAAAI,UAAA,GAAAJ,OAAA;AAEA,IAAAK,OAAA,GAAAL,OAAA;AACA,IAAAM,QAAA,GAAAN,OAAA;AAEA,IAAAO,aAAA,GAAAP,OAAA;AACA,IAAAQ,GAAA,GAAAC,uBAAA,CAAAT,OAAA;AACA,IAAAU,GAAA,GAAAV,OAAA;AAA2C,SAAAS,wBAAAE,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAJ,uBAAA,YAAAA,CAAAE,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAE3C;;;AAGO,MAAMkB,IAAI,GAAAC,OAAA,CAAAD,IAAA,GAAGE,aAAK;AACzB;;;AAGO,MAAMC,MAAM,GAAAF,OAAA,CAAAE,MAAA,GAAGC,eAAO;AAIvB,MAAOC,qBAAsB,SAAQC,mCAAsB;AAAAL,OAAA,CAAAI,qBAAA,GAAAA,qBAAA;AAYjE,MAAME,OAAO,GAAMC,GAAY,IAA4B,IAAAC,sBAAW,EAACD,GAAG,EAAEE,aAAK,CAACC,YAAY,CAAC,IAAI,IAAAF,sBAAW,EAACD,GAAG,CAACE,aAAK,CAACC,YAAY,CAAC,EAAE,SAAS,CAAC;AAClJ,MAAMC,QAAQ,GAAWJ,GAAY,IAAkC,IAAAC,sBAAW,EAACD,GAAG,EAAEK,oBAAY,CAAC;AACrG,MAAMC,iBAAiB,GAAON,GAAY,IAAgD,IAAAC,sBAAW,EAACD,GAAG,EAAEO,uBAAe,CAACC,qBAAqB,CAAC;AAEjJ;;;AAGM,MAAOC,KAAM,sBAAQC,cAAM,CAACC,OAAO,EAAS,CAAC,OAAO,EAAE;EACxDC,MAAM,eAAEF,cAAM,CAACG,GAAG,CAAC,aAAS;IACxB,MAAMC,MAAM,GAAuBd,GAAsB,IAAI;MACzD,IAAIe,MAA4B;MAChC,IAAG,IAAAC,kBAAS,EAAChB,GAAG,CAAC,EAAE;QACfe,MAAM,GAAGE,cAAM,CAACC,WAAW,CAAQlB,GAAG,CAAC;MAC3C,CAAC,MAAM,IAAIM,iBAAiB,CAAIN,GAAG,CAAC,EAAE;QAClCe,MAAM,GAAGf,GAAG,CAACmB,OAAO;MACxB,CAAC,MAAM,IAAG,IAAAC,gBAAQ,EAACpB,GAAG,CAAC,IAAI,CAACD,OAAO,CAAIC,GAAG,CAAC,EAAE;QACzCe,MAAM,GAAGE,cAAM,CAACI,UAAU,CAACrB,GAAG,CAAC;MACnC,CAAC,MAAM,IAAGD,OAAO,CAAIC,GAAG,CAAC,EAAE;QACvBe,MAAM,GAAGE,cAAM,CAACK,SAAS,CAACtB,GAAG,CAAC;MAClC,CAAC,MAAM,IAAGI,QAAQ,CAAQJ,GAAG,CAAC,EAAE;QAC5Be,MAAM,GAAGf,GAAG;MAChB,CAAC,MAAM;QACHe,MAAM,GAAGE,cAAM,CAACM,UAAU,CAACvB,GAAG,CAAC;MACnC;MACA,OAAOe,MAAM,CAACS,IAAI,CACdP,cAAM,CAACQ,qBAAqB,EAC5Bf,cAAM,CAACgB,OAAO,CAACC,IAAI,IAAI,IAAAC,0BAAY,EAACD,IAAI,CAAC,CAAC,CAC7C;IACL,CAAC;IACD,MAAME,QAAQ,GAAGA,CAAgBC,KAA4B,EAAEC,MAA6B,KAAI;MAC5F,IAAIA,MAAM,EAAE;QACR,OAAQ1D,CAAW,IAAKyD,KAAK,CAACC,MAAM,CAAC1D,CAAC,CAAC,CAAC;MAC5C;MACA,OAAOyD,KAAK;IAChB,CAAC;IAED,OAAO;MACH;;;;;;;;;;;;MAYAhB,MAAM;MACN;;;;;;;;;;;;;;;;;MAiBAe;KACH;EACL,CAAC;EACD;CACH,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;AAAApC,OAAA,CAAAgB,KAAA,GAAAA,KAAA;AAqBO,MAAMuB,WAAW,GAAGA,CAAsBC,YAAe,EAAEC,QAAoD,KAAKxB,cAAM,CAACG,GAAG,CAAC,aAAS;EAC3I,MAAMsB,MAAM,GAAG,OAAO5B,uBAAe,CAAC6B,IAAI,CAAIH,YAAY,CAAC;EAC3D,MAAMI,WAAW,GAAG,OAAOC,aAAK,CAACC,SAAS,EAAK;EAE/C,OAAO7B,cAAM,CAACG,GAAG,CAAC,aAAS;IACvB,MAAM2B,GAAG,GAAG,OAAOH,WAAW,CAACI,IAAI;IACnC,OAAOlC,uBAAe,CAACmC,YAAY,CAACP,MAAM,EAAEQ,KAAK,IAAIT,QAAQ,CAACS,KAAK,EAAEH,GAAG,CAAC,CAAC;EAC9E,CAAC,CAAC,CAAChB,IAAI,CACHd,cAAM,CAACkC,OAAO,EACdlC,cAAM,CAACmC,IAAI,CACd;EACD,MAAMC,QAAQ,GAAIN,GAAM,IAAKF,aAAK,CAACS,WAAW,CAACV,WAAW,EAAEG,GAAG,CAAC;EAEhE,OAAO;IAACzB,MAAM,EAAEoB,MAAM,CAAChB,OAAO;IAAE2B;EAAQ,CAAC;AAC7C,CAAC,CAAC;AAAArD,OAAA,CAAAuC,WAAA,GAAAA,WAAA;AAEK,MAAMgB,SAAS,GAAOf,YAAe,IAAKvB,cAAM,CAACG,GAAG,CAAC,aAAS;EACjE,MAAMsB,MAAM,GAAG,OAAO5B,uBAAe,CAAC6B,IAAI,CAAIH,YAAY,CAAC;EAC3D,MAAMI,WAAW,GAAG,OAAOC,aAAK,CAACC,SAAS,EAAiB;EAE3D,OAAO7B,cAAM,CAACG,GAAG,CAAC,aAAS;IACvB,MAAMqB,QAAQ,GAAG,OAAOG,WAAW,CAACI,IAAI;IACxC,OAAOlC,uBAAe,CAAC0C,MAAM,CAACd,MAAM,EAAED,QAAQ,CAAC;EACnD,CAAC,CAAC,CAACV,IAAI,CACHd,cAAM,CAACkC,OAAO,EACdlC,cAAM,CAACmC,IAAI,CACd;EACD,MAAM3D,GAAG,GAAIc,GAAM,IAAKsC,aAAK,CAACS,WAAW,CAACV,WAAW,EAAEa,CAAC,IAAIlD,GAAG,CAAC;EAChE,MAAMiD,MAAM,GAAIf,QAA4B,IAAKI,aAAK,CAACS,WAAW,CAACV,WAAW,EAACH,QAAQ,CAAC;EACxF,OAAO;IAACnB,MAAM,EAAEoB,MAAM,CAAChB,OAAO;IAAEjC,GAAG;IAAE+D;EAAM,CAAU;AACzD,CAAC,CAAC;AAEF;;;;AAAAxD,OAAA,CAAAuD,SAAA,GAAAA,SAAA;AAIM,MAAOG,UAAW,sBAAQC,eAAO,CAACC,GAAG,CAAC,YAAY,CAAC,EAQtD;EACC,OAAOC,IAAI,gBAAGC,aAAK,CAAC3C,MAAM,CAACuC,UAAU,eAAEzC,cAAM,CAACG,GAAG,CAAC,aAAS;IACvD,MAAM2C,GAAG,GAAG,OAAOC,WAAG,CAACrB,IAAI,CAAM,IAAIsB,GAAG,CAACC,MAAM,CAACC,UAAU,CAACC,YAAY,EAAEL,GAAI,CAAC,CAAC;IAC/E,MAAMM,UAAU,GAAG7C,cAAM,CAAC8C,iBAAiB,CAAgBJ,MAAM,CAACC,UAAU,EAAE,UAAU,CAAC,CAACpC,IAAI,CAC1FP,cAAM,CAAC+C,GAAG,CAAC3F,CAAC,IAAI,IAAIqF,GAAG,CAACrF,CAAC,CAAC4F,WAAW,CAACT,GAAG,CAAC,CAAC,EAC3CvC,cAAM,CAACiD,KAAK,CAACjD,cAAM,CAACmB,IAAI,CAAC,IAAIsB,GAAG,CAACC,MAAM,CAACC,UAAU,CAACC,YAAY,EAAEL,GAAI,CAAC,CAAC,CAAC,EACxEvC,cAAM,CAACkD,GAAG,CAACC,CAAC,IAAIX,WAAG,CAACvE,GAAG,CAACsE,GAAG,EAAEY,CAAC,CAAC,CAAC,CACnC;IACD,MAAMC,aAAa,GAAIC,IAAY,IAAK5D,cAAM,CAACG,GAAG,CAAC,aAAS;MACxD,MAAM0D,MAAM,GAAkB,CAAC,OAAOd,WAAG,CAACxE,GAAG,CAACuE,GAAG,CAAC,EAAEgB,YAAY,CAACvF,GAAG,CAACqF,IAAI,CAAC;MAC1E,IAAGC,MAAM,KAAK,IAAI,EAAE;QAChB,OAAO7D,cAAM,CAAC+D,IAAI,CAAC,IAAIC,6BAAsB,EAAE,CAAC;MACpD;MACA,OAAOH,MAAO;IAClB,CAAC,CAAC;IACF,OAAO;MACH;;;MAGAf,GAAG;MACH;;;MAGAM,UAAU;MACV;;;MAGAa,QAAQ,EAAEhB,MAAM,CAACC,UAAU,CAACe,QAAQ;MACpC;;;MAGAN;KACH;EACL,CAAC,CAAC,CAAC;;;AASA,MAAMO,eAAe,GAAWhE,MAA4B,IAAI;EACnE,MAAM;IAAEiE,OAAO;IAAEC,OAAO;IAAEC,OAAO;IAAEC,GAAG;IAAEC;EAAM,CAAE,GAAGC,YAAI,CAACC,UAAU,EAAmB;EACrF,MAAMC,WAAW,GAAGnE,cAAM,CAACmB,IAAI,CAACyC,OAAO,EAAE,CAAC;EAC1C,MAAMQ,YAAY,GAA2CpE,cAAM,CAACqE,SAAS,CACzEC,IAAI,IAAI7E,cAAM,CAACG,GAAG,CAAC,aAAS;IACxB,MAAM0D,MAAM,GAAG,OAAO3D,MAAM,CAACY,IAAI,CAC7Bd,cAAM,CAACsD,GAAG,CAACwB,IAAI,IAAIV,OAAO,CAAC;MAACU;IAAI,CAAC,CAAC,CAAC,EACnC9E,cAAM,CAAC+E,QAAQ,CAACC,KAAK,IAAIX,OAAO,CAAC;MAACW;IAAK,CAAC,CAAC,CAAC,EAC1ChF,cAAM,CAACwD,KAAK,CACf;IACDqB,IAAI,CAACI,MAAM,CAACpB,MAAM,CAAC;EACvB,CAAC,CAAC,CACL;EAED,OAAO;IAACxD,MAAM,EAAEE,cAAM,CAAC2E,MAAM,CAACR,WAAW,EAAEC,YAAY,CAAC;IAAEQ,EAAE,EAAEb,GAAG;IAAEc,KAAK,EAAEb;EAAM,CAAC;AACrF,CAAC;AAAAxF,OAAA,CAAAmF,eAAA,GAAAA,eAAA;AAGM,MAAMmB,KAAK,GAAAtG,OAAA,CAAAsG,KAAA,gBAAGtF,KAAK,CAACuF,OAAO,CAACxE,IAAI,cACnC+B,aAAK,CAAC0C,YAAY,CAAC9C,UAAU,CAACG,IAAI,CAAC,eACnCC,aAAK,CAAC2C,OAAO,cAAChI,GAAG,CAACiI,UAAU,CAACxC,MAAM,CAAC,CAAC,eACrCJ,aAAK,CAAC2C,OAAO,CAACE,mBAAe,CAACC,YAAY,CAAC,CAC9C","ignoreList":[]}
@@ -0,0 +1,169 @@
1
+ import { Chunk, Context, Data, Effect, Layer, Queue, Ref, Stream, SubscriptionRef, Unify } from "effect";
2
+ import { NoSuchElementException } from "effect/Cause";
3
+ import { type Channel } from "effect/Channel";
4
+ import { type PubSub } from "effect/PubSub";
5
+ import { type TemplateResult as _TemplateResult } from "lit-html";
6
+ import type { DirectiveClass, DirectiveResult as _DirectiveResult } from "lit-html/directive.js";
7
+ import { AsyncReplaceDirective as _AsyncReplaceDirective } from "lit-html/directives/async-replace.js";
8
+ /**
9
+ * Create an HTML template result that can be rendered to the DOM
10
+ */
11
+ export declare const html: (strings: TemplateStringsArray, ...values: unknown[]) => _TemplateResult<1>;
12
+ /**
13
+ * Renders a template result to the container
14
+ */
15
+ export declare const render: {
16
+ (value: unknown, container: import("lit-html").RenderRootNode, options?: import("lit-html").RenderOptions): import("lit-html").RootPart;
17
+ setSanitizer: (newSanitizer: import("lit-html").SanitizerFactory) => void;
18
+ createSanitizer: import("lit-html").SanitizerFactory;
19
+ _testOnlyClearSanitizerFactoryDoNotCallOrElse: () => void;
20
+ };
21
+ export type TemplateResult = _TemplateResult;
22
+ export type DirectiveResult<C extends DirectiveClass = DirectiveClass> = _DirectiveResult<C>;
23
+ export declare class AsyncReplaceDirective extends _AsyncReplaceDirective {
24
+ }
25
+ /**
26
+ * Types that can be attached to the DOM template using Effer's 'attach' method
27
+ */
28
+ export type Attachable<A, E, R> = Channel<Chunk.Chunk<A>, unknown, E, unknown, unknown, unknown, R> | Effect.Effect<A, E, R> | SubscriptionRef.SubscriptionRef<A> | PubSub<A> | Queue.Queue<A> | Stream.Stream<A, E, R>;
29
+ declare const Effer_base: Effect.Service.Class<Effer, "Effer", {
30
+ readonly effect: Effect.Effect<{
31
+ /**
32
+ * Attaches any Attachable value to the template:
33
+ * ```ts
34
+ * const Counter = () => Effect.gen(function*() {
35
+ * [ countRef, countQueue ] = yield* CounterService // service made with makeReducer or makeState
36
+ *
37
+ * return html`
38
+ * <p>The count is ${yield* attach(countRef)}</p>
39
+ * `
40
+ * })
41
+ * ```
42
+ */
43
+ attach: <A, E = never, R = never>(val: Attachable<A, E, R>) => Effect.Effect<_DirectiveResult<typeof _AsyncReplaceDirective>, never, R>;
44
+ /**
45
+ * Used in place of an event handler callback, this function takes a queue to dispatch messages to,
46
+ * as well as a mapping function from the DOM event to the queue's expected event type
47
+ * ```ts
48
+ * const Counter = () => Effect.gen(function*() {
49
+ * [ countRef, countQueue ] = yield* CounterService // service made with makeReducer
50
+ *
51
+ * return html`
52
+ * <button
53
+ * @click=${queueMsg(countQueue, () => Increment())}
54
+ * > // Increment() is an action defined as part of the CounterService reducer
55
+ * The count is ${yield* attach(countRef)}
56
+ * </button>
57
+ * `
58
+ * })
59
+ * ```
60
+ */
61
+ queueMsg: <DOMEvent, Msg>(offer: (msg: Msg) => boolean, mapper?: (e: DOMEvent) => Msg) => ((msg: Msg) => boolean) | ((e: DOMEvent) => boolean);
62
+ }, never, never>;
63
+ }>;
64
+ /**
65
+ * The Effer service provides methods for attaching Attachable values to the template and queueing events
66
+ */
67
+ export declare class Effer extends Effer_base {
68
+ }
69
+ /**
70
+ * Creates a stream of the latest state value, and a queue to update the value.
71
+ * @param initialState The starting state value
72
+ * @param updateFn An effectful function that takes the old state, an update message, and returns a new state
73
+ * @returns A tuple of the stream of the current state value and a queue to dispatch update messages
74
+ *
75
+ * ```ts
76
+ * type Msg = Data.TaggedEnum<{
77
+ * Increment: {};
78
+ * Decrement: {};
79
+ * }>
80
+ * const { Increment, Decrement, $match } = Data.taggedEnum<Msg>()
81
+ * const counterReducer = (state: number, msg: Msg) => $match({
82
+ * Increment: () => Effect.succeed(state + 1),
83
+ * Decrement: () => Effect.succeed(state - 1)
84
+ * })
85
+ *
86
+ * // Inside an Effect
87
+ * const [ countStream, countQueue ] = yield* makeReducer(0, counterReducer)
88
+ * ```
89
+ */
90
+ export declare const makeReducer: <A, M, E = never, R = never>(initialState: A, updateFn: (state: A, msg: M) => Effect.Effect<A, E, R>) => Effect.Effect<{
91
+ stream: Stream.Stream<A, never, never>;
92
+ dispatch: (msg: M) => boolean;
93
+ }, never, R>;
94
+ export declare const makeState: <A>(initialState: A) => Effect.Effect<{
95
+ readonly stream: Stream.Stream<A, never, never>;
96
+ readonly set: (val: A) => boolean;
97
+ readonly update: (updateFn: (oldValue: A) => A) => boolean;
98
+ }, never, never>;
99
+ declare const NavService_base: Context.TagClass<NavService, "NavService", {
100
+ url: Ref.Ref<URL>;
101
+ pathStream: Stream.Stream<URL>;
102
+ getQueryParam: (name: string) => Effect.Effect<string, NoSuchElementException, never>;
103
+ navigate: typeof window.navigation.navigate;
104
+ }>;
105
+ /**
106
+ * Effer's service to interact with navigation. Provides the current URL object, a stream of the
107
+ * current app path, a method to get a query param from the URL, and a method to navigate the page.
108
+ */
109
+ export declare class NavService extends NavService_base {
110
+ static Live: Layer.Layer<NavService, never, never>;
111
+ }
112
+ export type RemoteData<T, E> = Data.TaggedEnum<{
113
+ Loading: {};
114
+ Success: {
115
+ readonly data: T;
116
+ };
117
+ Failure: {
118
+ readonly error: E;
119
+ };
120
+ }> & {};
121
+ export declare const makeAsyncResult: <A, E, R>(effect: Effect.Effect<A, E, R>) => {
122
+ stream: Stream.Stream<RemoteData<A, E>, never, R>;
123
+ is: <Tag extends "Loading" | "Success" | "Failure">(tag: Tag) => (u: unknown) => u is Extract<{
124
+ readonly _tag: "Loading";
125
+ }, {
126
+ readonly _tag: Tag;
127
+ }> | Extract<{
128
+ readonly _tag: "Success";
129
+ readonly data: A;
130
+ }, {
131
+ readonly _tag: Tag;
132
+ }> | Extract<{
133
+ readonly _tag: "Failure";
134
+ readonly error: E;
135
+ }, {
136
+ readonly _tag: Tag;
137
+ }>;
138
+ match: {
139
+ <const Cases extends {
140
+ readonly Loading: (args: {
141
+ readonly _tag: "Loading";
142
+ }) => any;
143
+ readonly Success: (args: {
144
+ readonly _tag: "Success";
145
+ readonly data: A;
146
+ }) => any;
147
+ readonly Failure: (args: {
148
+ readonly _tag: "Failure";
149
+ readonly error: E;
150
+ }) => any;
151
+ }>(cases: Cases & { [K in Exclude<keyof Cases, "Loading" | "Success" | "Failure">]: never; }): (value: RemoteData<A, E>) => Unify.Unify<ReturnType<Cases["Loading" | "Success" | "Failure"]>>;
152
+ <const Cases extends {
153
+ readonly Loading: (args: {
154
+ readonly _tag: "Loading";
155
+ }) => any;
156
+ readonly Success: (args: {
157
+ readonly _tag: "Success";
158
+ readonly data: A;
159
+ }) => any;
160
+ readonly Failure: (args: {
161
+ readonly _tag: "Failure";
162
+ readonly error: E;
163
+ }) => any;
164
+ }>(value: RemoteData<A, E>, cases: Cases & { [K in Exclude<keyof Cases, "Loading" | "Success" | "Failure">]: never; }): Unify.Unify<ReturnType<Cases["Loading" | "Success" | "Failure"]>>;
165
+ };
166
+ };
167
+ export declare const layer: Layer.Layer<Effer | NavService, never, never>;
168
+ export {};
169
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}