unwrapped 0.1.0 → 0.1.2

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.
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/vue/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AsyncResultLoader: () => AsyncResultLoader,
24
+ buildCustomAsyncResultLoader: () => buildCustomAsyncResultLoader,
25
+ useAsyncResultRef: () => useAsyncResultRef,
26
+ useAsyncResultRefFromPromise: () => useAsyncResultRefFromPromise,
27
+ useGenerator: () => useGenerator,
28
+ useImmediateAction: () => useImmediateAction,
29
+ useLazyAction: () => useLazyAction,
30
+ useLazyGenerator: () => useLazyGenerator,
31
+ useReactiveAction: () => useReactiveAction,
32
+ useReactiveGenerator: () => useReactiveGenerator,
33
+ useReactiveResult: () => useReactiveResult
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/vue/composables.ts
38
+ var import_vue = require("vue");
39
+ var import_core = require("unwrapped/core");
40
+ function useAsyncResultRef(asyncResult) {
41
+ const state = (0, import_vue.ref)(asyncResult);
42
+ const unsub = asyncResult.listen(() => {
43
+ (0, import_vue.triggerRef)(state);
44
+ });
45
+ (0, import_vue.onUnmounted)(() => {
46
+ unsub();
47
+ });
48
+ return state;
49
+ }
50
+ function useReactiveResult(source, pipe, options = { immediate: true }) {
51
+ const result = new import_core.AsyncResult();
52
+ const resultRef = useAsyncResultRef(result);
53
+ let unsub = null;
54
+ (0, import_vue.watch)(source, (newInputs) => {
55
+ unsub?.();
56
+ unsub = result.mirror(pipe(newInputs));
57
+ }, { immediate: options.immediate });
58
+ (0, import_vue.onUnmounted)(() => {
59
+ unsub?.();
60
+ });
61
+ return resultRef;
62
+ }
63
+ function useAsyncResultRefFromPromise(promise) {
64
+ return useAsyncResultRef(import_core.AsyncResult.fromResultPromise(promise));
65
+ }
66
+ function useImmediateAction(action) {
67
+ return useAsyncResultRefFromPromise(action());
68
+ }
69
+ function useLazyAction(action) {
70
+ const result = new import_core.AsyncResult();
71
+ const resultRef = useAsyncResultRef(result);
72
+ const trigger = () => {
73
+ result.updateFromResultPromise(action());
74
+ };
75
+ return { resultRef, trigger };
76
+ }
77
+ function useReactiveAction(input, pipe, options = { immediate: true }) {
78
+ const source = typeof input === "function" ? (0, import_vue.computed)(input) : (0, import_vue.toRef)(input);
79
+ const outputRef = (0, import_vue.ref)(new import_core.AsyncResult());
80
+ let unsub = null;
81
+ (0, import_vue.watch)(source, () => {
82
+ unsub?.();
83
+ const newOutput = pipe(source.value);
84
+ unsub = newOutput.listen((newState) => {
85
+ outputRef.value.setState(newState.state);
86
+ (0, import_vue.triggerRef)(outputRef);
87
+ });
88
+ }, { immediate: options.immediate });
89
+ (0, import_vue.onUnmounted)(() => {
90
+ unsub?.();
91
+ });
92
+ return outputRef;
93
+ }
94
+ function useGenerator(generatorFunc) {
95
+ const resultRef = useAsyncResultRef(import_core.AsyncResult.run(generatorFunc));
96
+ return resultRef;
97
+ }
98
+ function useLazyGenerator(generatorFunc) {
99
+ const result = new import_core.AsyncResult();
100
+ const resultRef = useAsyncResultRef(result);
101
+ const trigger = () => {
102
+ result.runInPlace(generatorFunc);
103
+ };
104
+ return { resultRef, trigger };
105
+ }
106
+ function useReactiveGenerator(source, generatorFunc, options = { immediate: true }) {
107
+ const resultRef = useAsyncResultRef(new import_core.AsyncResult());
108
+ (0, import_vue.watch)(source, (newInputs) => {
109
+ resultRef.value.runInPlace(() => generatorFunc(newInputs));
110
+ }, { immediate: options.immediate });
111
+ return resultRef;
112
+ }
113
+
114
+ // src/vue/components/asyncResultLoader.ts
115
+ var import_vue2 = require("vue");
116
+ var AsyncResultLoader = (0, import_vue2.defineComponent)({
117
+ name: "AsyncResultLoader",
118
+ props: {
119
+ result: {
120
+ type: Object,
121
+ required: true
122
+ }
123
+ },
124
+ setup(props, { slots }) {
125
+ const state = (0, import_vue2.ref)(props.result.state);
126
+ let unlisten = null;
127
+ (0, import_vue2.onUnmounted)(() => {
128
+ if (unlisten) unlisten();
129
+ });
130
+ (0, import_vue2.watch)(
131
+ () => props.result,
132
+ (newResult) => {
133
+ if (unlisten) unlisten();
134
+ state.value = newResult.state;
135
+ unlisten = newResult.listen((res) => {
136
+ state.value = res.state;
137
+ });
138
+ },
139
+ { immediate: true }
140
+ );
141
+ return () => {
142
+ const s = state.value;
143
+ switch (s.status) {
144
+ case "loading":
145
+ return slots.loading ? slots.loading() : (0, import_vue2.h)("div", { class: "loading" }, "Loading\u2026");
146
+ case "error":
147
+ return slots.error ? slots.error({ error: s.error }) : (0, import_vue2.h)("div", { class: "error" }, `Error: ${s.error}`);
148
+ case "success":
149
+ return slots.default ? slots.default({ value: s.value }) : null;
150
+ default:
151
+ return slots.idle ? slots.idle() : (0, import_vue2.h)("div", { class: "idle" }, "Idle");
152
+ }
153
+ };
154
+ }
155
+ });
156
+ function buildCustomAsyncResultLoader(slots) {
157
+ const comp = (0, import_vue2.defineComponent)({
158
+ name: "CustomAsyncResultLoader",
159
+ props: {
160
+ result: {
161
+ type: Object,
162
+ required: true
163
+ }
164
+ },
165
+ setup(props, context) {
166
+ return () => {
167
+ const renderLoading = context.slots.loading ?? slots.loading ?? (() => void 0);
168
+ const renderError = context.slots.error ?? slots.error ?? (() => void 0);
169
+ return (0, import_vue2.h)(
170
+ AsyncResultLoader,
171
+ { result: props.result },
172
+ {
173
+ default: context.slots.default ? (propsDefault) => context.slots.default(propsDefault) : void 0,
174
+ loading: () => renderLoading(),
175
+ error: ((propsError) => renderError(propsError))
176
+ }
177
+ );
178
+ };
179
+ }
180
+ });
181
+ return comp;
182
+ }
183
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/vue/index.ts","../../src/vue/composables.ts","../../src/vue/components/asyncResultLoader.ts"],"sourcesContent":["export * from \"./composables\"\nexport * from \"./components/asyncResultLoader\"","import { computed, onUnmounted, ref, toRef, triggerRef, watch, type Ref, type WatchSource } from \"vue\";\nimport { AsyncResult, type FlatChainFunction, type Result } from \"unwrapped/core\";\n\nexport function useAsyncResultRef<T, E>(asyncResult: AsyncResult<T, E>) {\n const state = ref<AsyncResult<T, E>>(asyncResult) as Ref<AsyncResult<T, E>>;\n\n const unsub = asyncResult.listen(() => {\n triggerRef(state);\n });\n\n onUnmounted(() => {\n unsub();\n });\n\n return state;\n}\n\nexport function useReactiveResult<T, E, Inputs>(source: WatchSource<Inputs>, pipe: FlatChainFunction<Inputs, T, E>, options:{ immediate: boolean } = { immediate: true }): Ref<AsyncResult<T, E>> {\n const result = new AsyncResult<T, E>();\n const resultRef = useAsyncResultRef(result);\n\n let unsub: (() => void) | null = null;\n\n watch(source, (newInputs) => {\n unsub?.();\n unsub = result.mirror(pipe(newInputs));\n }, { immediate: options.immediate });\n \n onUnmounted(() => {\n unsub?.();\n });\n\n return resultRef;\n}\n\nexport function useAsyncResultRefFromPromise<T, E>(promise: Promise<Result<T, E>>) {\n return useAsyncResultRef(AsyncResult.fromResultPromise(promise));\n}\n\nexport type Action<T,E> = () => Promise<Result<T, E>>;\nexport function useImmediateAction<T, E>(action: Action<T, E>): Ref<AsyncResult<T, E>> {\n return useAsyncResultRefFromPromise(action());\n}\nexport interface LazyActionReturn<T, E> {\n resultRef: Ref<AsyncResult<T, E>>;\n trigger: () => void;\n}\n\nexport function useLazyAction<T, E>(action: Action<T, E>): LazyActionReturn<T, E> {\n const result = new AsyncResult<T, E>();\n const resultRef = useAsyncResultRef(result);\n\n const trigger = () => {\n result.updateFromResultPromise(action());\n }\n\n return { resultRef, trigger };\n}\n\nexport function useReactiveAction<I, O, E>(input: I | Ref<I> | (() => I), pipe: FlatChainFunction<I, O, E>, options:{ immediate: boolean } = { immediate: true }): Ref<AsyncResult<O, E>> {\n const source = typeof input === 'function' ? computed(input as () => I) : toRef(input)\n\n const outputRef = ref<AsyncResult<O, E>>(new AsyncResult()) as Ref<AsyncResult<O, E>>;\n let unsub: (() => void) | null = null;\n\n watch(source, () => {\n unsub?.();\n const newOutput = pipe(source.value);\n unsub = newOutput.listen((newState) => {\n outputRef.value.setState(newState.state);\n triggerRef(outputRef);\n });\n }, { immediate: options.immediate });\n\n onUnmounted(() => {\n unsub?.();\n });\n\n return outputRef;\n}\n\nexport function useGenerator<T>(generatorFunc: () => Generator<AsyncResult<any, any>, T, any>): Ref<AsyncResult<T, any>> {\n const resultRef = useAsyncResultRef(AsyncResult.run(generatorFunc));\n return resultRef;\n}\n\nexport function useLazyGenerator<T>(generatorFunc: () => Generator<AsyncResult<any, any>, T, any>): { resultRef: Ref<AsyncResult<T, any>>, trigger: () => void } {\n const result = new AsyncResult<T, any>();\n const resultRef = useAsyncResultRef(result);\n\n const trigger = () => {\n result.runInPlace(generatorFunc);\n }\n\n return { resultRef, trigger };\n}\n\nexport function useReactiveGenerator<T, E, Inputs>(source: WatchSource<Inputs>, generatorFunc: (args: Inputs) => Generator<AsyncResult<any, any>, T, any>, options:{ immediate: boolean } = { immediate: true }): Ref<AsyncResult<T, E>> {\n const resultRef = useAsyncResultRef(new AsyncResult<T, E>());\n\n watch(source, (newInputs) => {\n resultRef.value.runInPlace(() => generatorFunc(newInputs));\n }, { immediate: options.immediate });\n\n return resultRef;\n}","import { defineComponent, ref, watch, onUnmounted, h, type VNode } from \"vue\"\nimport type { AsyncResult, AsyncResultState } from \"unwrapped/core\"\n\nexport const AsyncResultLoader = defineComponent({\n name: \"AsyncResultLoader\",\n\n props: {\n result: {\n type: Object as () => AsyncResult<unknown, unknown>,\n required: true\n }\n },\n\n setup(props, { slots }) {\n const state = ref<AsyncResultState<unknown, unknown>>(props.result.state)\n let unlisten: (() => void) | null = null\n\n // Unsubscribe on destroy\n onUnmounted(() => {\n if (unlisten) unlisten()\n })\n\n // Watch for prop changes & update listener\n watch(\n () => props.result,\n (newResult) => {\n if (unlisten) unlisten()\n state.value = newResult.state\n unlisten = newResult.listen((res) => {\n state.value = res.state\n })\n },\n { immediate: true }\n )\n\n return () => {\n const s = state.value\n\n // Choose what to render based on status\n switch (s.status) {\n case \"loading\":\n return slots.loading\n ? slots.loading()\n : h(\"div\", { class: \"loading\" }, \"Loading…\")\n\n case \"error\":\n return slots.error\n ? slots.error({ error: s.error })\n : h(\"div\", { class: \"error\" }, `Error: ${s.error}`)\n\n case \"success\":\n return slots.default\n ? slots.default({ value: s.value })\n : null\n\n default:\n // \"idle\"\n return slots.idle\n ? slots.idle()\n : h(\"div\", { class: \"idle\" }, \"Idle\")\n }\n }\n }\n})\n\ninterface CustomSlots<E> {\n loading?: () => VNode;\n error?: (props: { error: E }) => VNode;\n}\n\nexport function buildCustomAsyncResultLoader<T, E>(slots: CustomSlots<E>) {\n const comp = defineComponent({\n name: \"CustomAsyncResultLoader\",\n props: {\n result: {\n type: Object as () => AsyncResult<T, E>,\n required: true\n }\n },\n setup(props, context) {\n return () => {\n const renderLoading = context.slots.loading ?? slots.loading ?? (() => undefined);\n const renderError = context.slots.error ?? slots.error ?? (() => undefined);\n return h(\n AsyncResultLoader,\n { result: props.result },\n {\n default: context.slots.default ? (propsDefault: { value: T }) => context.slots.default!(propsDefault) : undefined,\n\n loading: () => renderLoading(),\n error: ((propsError: { error: E }) => renderError(propsError))\n }\n )\n }\n }\n });\n\n return comp;\n}\n"],"mappings":"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","names":["import_vue"]}
@@ -0,0 +1,160 @@
1
+ // src/vue/composables.ts
2
+ import { computed, onUnmounted, ref, toRef, triggerRef, watch } from "vue";
3
+ import { AsyncResult } from "unwrapped/core";
4
+ function useAsyncResultRef(asyncResult) {
5
+ const state = ref(asyncResult);
6
+ const unsub = asyncResult.listen(() => {
7
+ triggerRef(state);
8
+ });
9
+ onUnmounted(() => {
10
+ unsub();
11
+ });
12
+ return state;
13
+ }
14
+ function useReactiveResult(source, pipe, options = { immediate: true }) {
15
+ const result = new AsyncResult();
16
+ const resultRef = useAsyncResultRef(result);
17
+ let unsub = null;
18
+ watch(source, (newInputs) => {
19
+ unsub?.();
20
+ unsub = result.mirror(pipe(newInputs));
21
+ }, { immediate: options.immediate });
22
+ onUnmounted(() => {
23
+ unsub?.();
24
+ });
25
+ return resultRef;
26
+ }
27
+ function useAsyncResultRefFromPromise(promise) {
28
+ return useAsyncResultRef(AsyncResult.fromResultPromise(promise));
29
+ }
30
+ function useImmediateAction(action) {
31
+ return useAsyncResultRefFromPromise(action());
32
+ }
33
+ function useLazyAction(action) {
34
+ const result = new AsyncResult();
35
+ const resultRef = useAsyncResultRef(result);
36
+ const trigger = () => {
37
+ result.updateFromResultPromise(action());
38
+ };
39
+ return { resultRef, trigger };
40
+ }
41
+ function useReactiveAction(input, pipe, options = { immediate: true }) {
42
+ const source = typeof input === "function" ? computed(input) : toRef(input);
43
+ const outputRef = ref(new AsyncResult());
44
+ let unsub = null;
45
+ watch(source, () => {
46
+ unsub?.();
47
+ const newOutput = pipe(source.value);
48
+ unsub = newOutput.listen((newState) => {
49
+ outputRef.value.setState(newState.state);
50
+ triggerRef(outputRef);
51
+ });
52
+ }, { immediate: options.immediate });
53
+ onUnmounted(() => {
54
+ unsub?.();
55
+ });
56
+ return outputRef;
57
+ }
58
+ function useGenerator(generatorFunc) {
59
+ const resultRef = useAsyncResultRef(AsyncResult.run(generatorFunc));
60
+ return resultRef;
61
+ }
62
+ function useLazyGenerator(generatorFunc) {
63
+ const result = new AsyncResult();
64
+ const resultRef = useAsyncResultRef(result);
65
+ const trigger = () => {
66
+ result.runInPlace(generatorFunc);
67
+ };
68
+ return { resultRef, trigger };
69
+ }
70
+ function useReactiveGenerator(source, generatorFunc, options = { immediate: true }) {
71
+ const resultRef = useAsyncResultRef(new AsyncResult());
72
+ watch(source, (newInputs) => {
73
+ resultRef.value.runInPlace(() => generatorFunc(newInputs));
74
+ }, { immediate: options.immediate });
75
+ return resultRef;
76
+ }
77
+
78
+ // src/vue/components/asyncResultLoader.ts
79
+ import { defineComponent, ref as ref2, watch as watch2, onUnmounted as onUnmounted2, h } from "vue";
80
+ var AsyncResultLoader = defineComponent({
81
+ name: "AsyncResultLoader",
82
+ props: {
83
+ result: {
84
+ type: Object,
85
+ required: true
86
+ }
87
+ },
88
+ setup(props, { slots }) {
89
+ const state = ref2(props.result.state);
90
+ let unlisten = null;
91
+ onUnmounted2(() => {
92
+ if (unlisten) unlisten();
93
+ });
94
+ watch2(
95
+ () => props.result,
96
+ (newResult) => {
97
+ if (unlisten) unlisten();
98
+ state.value = newResult.state;
99
+ unlisten = newResult.listen((res) => {
100
+ state.value = res.state;
101
+ });
102
+ },
103
+ { immediate: true }
104
+ );
105
+ return () => {
106
+ const s = state.value;
107
+ switch (s.status) {
108
+ case "loading":
109
+ return slots.loading ? slots.loading() : h("div", { class: "loading" }, "Loading\u2026");
110
+ case "error":
111
+ return slots.error ? slots.error({ error: s.error }) : h("div", { class: "error" }, `Error: ${s.error}`);
112
+ case "success":
113
+ return slots.default ? slots.default({ value: s.value }) : null;
114
+ default:
115
+ return slots.idle ? slots.idle() : h("div", { class: "idle" }, "Idle");
116
+ }
117
+ };
118
+ }
119
+ });
120
+ function buildCustomAsyncResultLoader(slots) {
121
+ const comp = defineComponent({
122
+ name: "CustomAsyncResultLoader",
123
+ props: {
124
+ result: {
125
+ type: Object,
126
+ required: true
127
+ }
128
+ },
129
+ setup(props, context) {
130
+ return () => {
131
+ const renderLoading = context.slots.loading ?? slots.loading ?? (() => void 0);
132
+ const renderError = context.slots.error ?? slots.error ?? (() => void 0);
133
+ return h(
134
+ AsyncResultLoader,
135
+ { result: props.result },
136
+ {
137
+ default: context.slots.default ? (propsDefault) => context.slots.default(propsDefault) : void 0,
138
+ loading: () => renderLoading(),
139
+ error: ((propsError) => renderError(propsError))
140
+ }
141
+ );
142
+ };
143
+ }
144
+ });
145
+ return comp;
146
+ }
147
+ export {
148
+ AsyncResultLoader,
149
+ buildCustomAsyncResultLoader,
150
+ useAsyncResultRef,
151
+ useAsyncResultRefFromPromise,
152
+ useGenerator,
153
+ useImmediateAction,
154
+ useLazyAction,
155
+ useLazyGenerator,
156
+ useReactiveAction,
157
+ useReactiveGenerator,
158
+ useReactiveResult
159
+ };
160
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/vue/composables.ts","../../src/vue/components/asyncResultLoader.ts"],"sourcesContent":["import { computed, onUnmounted, ref, toRef, triggerRef, watch, type Ref, type WatchSource } from \"vue\";\nimport { AsyncResult, type FlatChainFunction, type Result } from \"unwrapped/core\";\n\nexport function useAsyncResultRef<T, E>(asyncResult: AsyncResult<T, E>) {\n const state = ref<AsyncResult<T, E>>(asyncResult) as Ref<AsyncResult<T, E>>;\n\n const unsub = asyncResult.listen(() => {\n triggerRef(state);\n });\n\n onUnmounted(() => {\n unsub();\n });\n\n return state;\n}\n\nexport function useReactiveResult<T, E, Inputs>(source: WatchSource<Inputs>, pipe: FlatChainFunction<Inputs, T, E>, options:{ immediate: boolean } = { immediate: true }): Ref<AsyncResult<T, E>> {\n const result = new AsyncResult<T, E>();\n const resultRef = useAsyncResultRef(result);\n\n let unsub: (() => void) | null = null;\n\n watch(source, (newInputs) => {\n unsub?.();\n unsub = result.mirror(pipe(newInputs));\n }, { immediate: options.immediate });\n \n onUnmounted(() => {\n unsub?.();\n });\n\n return resultRef;\n}\n\nexport function useAsyncResultRefFromPromise<T, E>(promise: Promise<Result<T, E>>) {\n return useAsyncResultRef(AsyncResult.fromResultPromise(promise));\n}\n\nexport type Action<T,E> = () => Promise<Result<T, E>>;\nexport function useImmediateAction<T, E>(action: Action<T, E>): Ref<AsyncResult<T, E>> {\n return useAsyncResultRefFromPromise(action());\n}\nexport interface LazyActionReturn<T, E> {\n resultRef: Ref<AsyncResult<T, E>>;\n trigger: () => void;\n}\n\nexport function useLazyAction<T, E>(action: Action<T, E>): LazyActionReturn<T, E> {\n const result = new AsyncResult<T, E>();\n const resultRef = useAsyncResultRef(result);\n\n const trigger = () => {\n result.updateFromResultPromise(action());\n }\n\n return { resultRef, trigger };\n}\n\nexport function useReactiveAction<I, O, E>(input: I | Ref<I> | (() => I), pipe: FlatChainFunction<I, O, E>, options:{ immediate: boolean } = { immediate: true }): Ref<AsyncResult<O, E>> {\n const source = typeof input === 'function' ? computed(input as () => I) : toRef(input)\n\n const outputRef = ref<AsyncResult<O, E>>(new AsyncResult()) as Ref<AsyncResult<O, E>>;\n let unsub: (() => void) | null = null;\n\n watch(source, () => {\n unsub?.();\n const newOutput = pipe(source.value);\n unsub = newOutput.listen((newState) => {\n outputRef.value.setState(newState.state);\n triggerRef(outputRef);\n });\n }, { immediate: options.immediate });\n\n onUnmounted(() => {\n unsub?.();\n });\n\n return outputRef;\n}\n\nexport function useGenerator<T>(generatorFunc: () => Generator<AsyncResult<any, any>, T, any>): Ref<AsyncResult<T, any>> {\n const resultRef = useAsyncResultRef(AsyncResult.run(generatorFunc));\n return resultRef;\n}\n\nexport function useLazyGenerator<T>(generatorFunc: () => Generator<AsyncResult<any, any>, T, any>): { resultRef: Ref<AsyncResult<T, any>>, trigger: () => void } {\n const result = new AsyncResult<T, any>();\n const resultRef = useAsyncResultRef(result);\n\n const trigger = () => {\n result.runInPlace(generatorFunc);\n }\n\n return { resultRef, trigger };\n}\n\nexport function useReactiveGenerator<T, E, Inputs>(source: WatchSource<Inputs>, generatorFunc: (args: Inputs) => Generator<AsyncResult<any, any>, T, any>, options:{ immediate: boolean } = { immediate: true }): Ref<AsyncResult<T, E>> {\n const resultRef = useAsyncResultRef(new AsyncResult<T, E>());\n\n watch(source, (newInputs) => {\n resultRef.value.runInPlace(() => generatorFunc(newInputs));\n }, { immediate: options.immediate });\n\n return resultRef;\n}","import { defineComponent, ref, watch, onUnmounted, h, type VNode } from \"vue\"\nimport type { AsyncResult, AsyncResultState } from \"unwrapped/core\"\n\nexport const AsyncResultLoader = defineComponent({\n name: \"AsyncResultLoader\",\n\n props: {\n result: {\n type: Object as () => AsyncResult<unknown, unknown>,\n required: true\n }\n },\n\n setup(props, { slots }) {\n const state = ref<AsyncResultState<unknown, unknown>>(props.result.state)\n let unlisten: (() => void) | null = null\n\n // Unsubscribe on destroy\n onUnmounted(() => {\n if (unlisten) unlisten()\n })\n\n // Watch for prop changes & update listener\n watch(\n () => props.result,\n (newResult) => {\n if (unlisten) unlisten()\n state.value = newResult.state\n unlisten = newResult.listen((res) => {\n state.value = res.state\n })\n },\n { immediate: true }\n )\n\n return () => {\n const s = state.value\n\n // Choose what to render based on status\n switch (s.status) {\n case \"loading\":\n return slots.loading\n ? slots.loading()\n : h(\"div\", { class: \"loading\" }, \"Loading…\")\n\n case \"error\":\n return slots.error\n ? slots.error({ error: s.error })\n : h(\"div\", { class: \"error\" }, `Error: ${s.error}`)\n\n case \"success\":\n return slots.default\n ? slots.default({ value: s.value })\n : null\n\n default:\n // \"idle\"\n return slots.idle\n ? slots.idle()\n : h(\"div\", { class: \"idle\" }, \"Idle\")\n }\n }\n }\n})\n\ninterface CustomSlots<E> {\n loading?: () => VNode;\n error?: (props: { error: E }) => VNode;\n}\n\nexport function buildCustomAsyncResultLoader<T, E>(slots: CustomSlots<E>) {\n const comp = defineComponent({\n name: \"CustomAsyncResultLoader\",\n props: {\n result: {\n type: Object as () => AsyncResult<T, E>,\n required: true\n }\n },\n setup(props, context) {\n return () => {\n const renderLoading = context.slots.loading ?? slots.loading ?? (() => undefined);\n const renderError = context.slots.error ?? slots.error ?? (() => undefined);\n return h(\n AsyncResultLoader,\n { result: props.result },\n {\n default: context.slots.default ? (propsDefault: { value: T }) => context.slots.default!(propsDefault) : undefined,\n\n loading: () => renderLoading(),\n error: ((propsError: { error: E }) => renderError(propsError))\n }\n )\n }\n }\n });\n\n return comp;\n}\n"],"mappings":"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","names":["ref","watch","onUnmounted"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unwrapped",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -1,8 +0,0 @@
1
- # Changesets
2
-
3
- Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4
- with multi-package repos, or single-package repos to help you version and publish your code. You can
5
- find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6
-
7
- We have a quick list of common questions to get you started engaging with this project in
8
- [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
@@ -1,11 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
3
- "changelog": "@changesets/cli/changelog",
4
- "commit": false,
5
- "fixed": [],
6
- "linked": [],
7
- "access": "restricted",
8
- "baseBranch": "main",
9
- "updateInternalDependencies": "patch",
10
- "ignore": []
11
- }
@@ -1,19 +0,0 @@
1
- name: CI
2
- on:
3
- push:
4
- branches:
5
- - "**"
6
-
7
- jobs:
8
- build:
9
- runs-on: ubuntu-latest
10
- steps:
11
- - uses: actions/checkout@v3
12
-
13
- - uses: actions/setup-node@v3
14
- with:
15
- node-version: 16.x
16
- cache: "npm"
17
-
18
- - run: npm ci
19
- - run: npm run lint && npm run build
@@ -1,36 +0,0 @@
1
- name: Publish
2
- on:
3
- workflow_run:
4
- workflows: [CI]
5
- branches: [main]
6
- types: [completed]
7
-
8
- concurrency: ${{ github.workflow }}-${{ github.ref }}
9
-
10
- permissions:
11
- id-token: write # Required for OIDC
12
- contents: write
13
- pull-requests: write
14
-
15
- jobs:
16
- publish:
17
- if: ${{ github.event.workflow_run.conclusion == 'success' }}
18
- runs-on: ubuntu-latest
19
- steps:
20
- - uses: actions/checkout@v3
21
-
22
- - uses: actions/setup-node@v3
23
- with:
24
- node-version: 16.x
25
- cache: "npm"
26
-
27
- - run: npm ci
28
-
29
- - name: Create Release Pull Request or Publish
30
- id: changesets
31
- uses: changesets/action@v1
32
- with:
33
- publish: npm run release
34
- env:
35
- GITHUB_TOKEN: ${{ secrets.PUBLISH_GITHUB_SECRET }}
36
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}