dtwo 2.17.0 → 3.0.0

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.
Files changed (118) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +2 -41
  3. package/app.d.ts +1 -0
  4. package/bin/dtwo.mjs +2 -0
  5. package/config.cjs +7 -0
  6. package/config.d.ts +4 -0
  7. package/config.mjs +5 -0
  8. package/dist/app/compat/capi.d.ts +4 -0
  9. package/dist/app/compat/capi.mjs +19 -0
  10. package/dist/app/compat/kdu-demi.d.ts +4 -0
  11. package/dist/app/compat/kdu-demi.mjs +4 -0
  12. package/dist/app/components/client-only.d.mts +22 -0
  13. package/dist/app/components/client-only.mjs +75 -0
  14. package/dist/app/components/dev-only.d.mts +4 -0
  15. package/dist/app/components/dev-only.mjs +11 -0
  16. package/dist/app/components/dtwo-error-boundary.d.ts +8 -0
  17. package/dist/app/components/dtwo-error-boundary.mjs +21 -0
  18. package/dist/app/components/dtwo-error-page.kdu +46 -0
  19. package/dist/app/components/dtwo-link.d.ts +33 -0
  20. package/dist/app/components/dtwo-link.mjs +248 -0
  21. package/dist/app/components/dtwo-loading-indicator.d.ts +43 -0
  22. package/dist/app/components/dtwo-loading-indicator.mjs +107 -0
  23. package/dist/app/components/dtwo-root.kdu +35 -0
  24. package/dist/app/components/index.d.ts +2 -0
  25. package/dist/app/components/index.mjs +1 -0
  26. package/dist/app/components/layout.d.ts +17 -0
  27. package/dist/app/components/layout.mjs +66 -0
  28. package/dist/app/components/server-placeholder.d.ts +2 -0
  29. package/dist/app/components/server-placeholder.mjs +7 -0
  30. package/dist/app/components/utils.d.ts +11 -0
  31. package/dist/app/components/utils.mjs +9 -0
  32. package/dist/app/composables/asyncData.d.ts +40 -0
  33. package/dist/app/composables/asyncData.mjs +169 -0
  34. package/dist/app/composables/component.d.ts +3 -0
  35. package/dist/app/composables/component.mjs +46 -0
  36. package/dist/app/composables/cookie.d.ts +12 -0
  37. package/dist/app/composables/cookie.mjs +58 -0
  38. package/dist/app/composables/error.d.ts +17 -0
  39. package/dist/app/composables/error.mjs +31 -0
  40. package/dist/app/composables/fetch.d.ts +15 -0
  41. package/dist/app/composables/fetch.mjs +66 -0
  42. package/dist/app/composables/hydrate.d.ts +8 -0
  43. package/dist/app/composables/hydrate.mjs +14 -0
  44. package/dist/app/composables/index.d.ts +16 -0
  45. package/dist/app/composables/index.mjs +11 -0
  46. package/dist/app/composables/payload.d.ts +8 -0
  47. package/dist/app/composables/payload.mjs +58 -0
  48. package/dist/app/composables/preload.d.ts +17 -0
  49. package/dist/app/composables/preload.mjs +41 -0
  50. package/dist/app/composables/router.d.ts +28 -0
  51. package/dist/app/composables/router.mjs +111 -0
  52. package/dist/app/composables/ssr.d.ts +6 -0
  53. package/dist/app/composables/ssr.mjs +23 -0
  54. package/dist/app/composables/state.d.ts +9 -0
  55. package/dist/app/composables/state.mjs +27 -0
  56. package/dist/app/config.d.ts +13 -0
  57. package/dist/app/config.mjs +56 -0
  58. package/dist/app/dtwo.d.ts +122 -0
  59. package/dist/app/dtwo.mjs +168 -0
  60. package/dist/app/entry.async.d.ts +2 -0
  61. package/dist/app/entry.async.mjs +5 -0
  62. package/dist/app/entry.d.ts +3 -0
  63. package/dist/app/entry.mjs +59 -0
  64. package/dist/app/index.d.ts +10 -0
  65. package/dist/app/index.mjs +7 -0
  66. package/dist/app/plugins/cross-origin-prefetch.client.d.ts +2 -0
  67. package/dist/app/plugins/cross-origin-prefetch.client.mjs +28 -0
  68. package/dist/app/plugins/debug.d.ts +2 -0
  69. package/dist/app/plugins/debug.mjs +5 -0
  70. package/dist/app/plugins/payload.client.d.ts +2 -0
  71. package/dist/app/plugins/payload.client.mjs +22 -0
  72. package/dist/app/plugins/preload.server.d.ts +2 -0
  73. package/dist/app/plugins/preload.server.mjs +10 -0
  74. package/dist/app/plugins/router.d.ts +53 -0
  75. package/dist/app/plugins/router.mjs +176 -0
  76. package/dist/app/types/augments.d.ts +28 -0
  77. package/dist/core/runtime/hole/error.d.ts +3 -0
  78. package/dist/core/runtime/hole/error.mjs +58 -0
  79. package/dist/core/runtime/hole/paths.d.ts +4 -0
  80. package/dist/core/runtime/hole/paths.mjs +15 -0
  81. package/dist/core/runtime/hole/renderer.d.ts +16 -0
  82. package/dist/core/runtime/hole/renderer.mjs +219 -0
  83. package/dist/head/runtime/components.d.ts +796 -0
  84. package/dist/head/runtime/components.mjs +209 -0
  85. package/dist/head/runtime/composables.d.ts +10 -0
  86. package/dist/head/runtime/composables.mjs +4 -0
  87. package/dist/head/runtime/index.d.ts +4 -0
  88. package/dist/head/runtime/index.mjs +1 -0
  89. package/dist/head/runtime/lib/kdu-meta.plugin.d.ts +2 -0
  90. package/dist/head/runtime/lib/kdu-meta.plugin.mjs +31 -0
  91. package/dist/head/runtime/lib/kduse-head.plugin.d.ts +2 -0
  92. package/dist/head/runtime/lib/kduse-head.plugin.mjs +35 -0
  93. package/dist/head/runtime/types.d.ts +7 -0
  94. package/dist/head/runtime/types.mjs +0 -0
  95. package/dist/index.d.ts +9 -0
  96. package/dist/index.mjs +2272 -0
  97. package/dist/pages/runtime/app.kdu +5 -0
  98. package/dist/pages/runtime/composables.d.ts +42 -0
  99. package/dist/pages/runtime/composables.mjs +8 -0
  100. package/dist/pages/runtime/index.d.ts +1 -0
  101. package/dist/pages/runtime/index.mjs +1 -0
  102. package/dist/pages/runtime/page-placeholder.d.ts +4 -0
  103. package/dist/pages/runtime/page-placeholder.mjs +10 -0
  104. package/dist/pages/runtime/page.d.ts +15 -0
  105. package/dist/pages/runtime/page.mjs +107 -0
  106. package/dist/pages/runtime/router.d.ts +8 -0
  107. package/dist/pages/runtime/router.mjs +152 -0
  108. package/dist/pages/runtime/router.options.d.ts +2 -0
  109. package/dist/pages/runtime/router.options.mjs +51 -0
  110. package/dist/pages/runtime/utils.d.ts +9 -0
  111. package/dist/pages/runtime/utils.mjs +12 -0
  112. package/dist/pages/runtime/validate.d.ts +2 -0
  113. package/dist/pages/runtime/validate.mjs +11 -0
  114. package/package.json +79 -42
  115. package/types.d.ts +15 -0
  116. package/bin/dtwo.js +0 -10
  117. package/dist/dtwo.js +0 -37
  118. package/webpack.config.js +0 -4
@@ -0,0 +1,107 @@
1
+ import { computed, defineComponent, h, onBeforeUnmount, ref } from "kdu";
2
+ import { useDtwoApp } from "#app";
3
+ export default defineComponent({
4
+ name: "DtwoLoadingIndicator",
5
+ props: {
6
+ throttle: {
7
+ type: Number,
8
+ default: 200
9
+ },
10
+ duration: {
11
+ type: Number,
12
+ default: 2e3
13
+ },
14
+ height: {
15
+ type: Number,
16
+ default: 3
17
+ },
18
+ color: {
19
+ type: String,
20
+ default: "repeating-linear-gradient(to right,#d7555d 0%,#e5757b 50%,#0047e1 100%)"
21
+ }
22
+ },
23
+ setup(props, { slots }) {
24
+ const indicator = useLoadingIndicator({
25
+ duration: props.duration,
26
+ throttle: props.throttle
27
+ });
28
+ const dtwoApp = useDtwoApp();
29
+ dtwoApp.hook("page:start", indicator.start);
30
+ dtwoApp.hook("page:finish", indicator.finish);
31
+ onBeforeUnmount(() => indicator.clear);
32
+ return () => h("div", {
33
+ class: "dtwo-loading-indicator",
34
+ style: {
35
+ position: "fixed",
36
+ top: 0,
37
+ right: 0,
38
+ left: 0,
39
+ pointerEvents: "none",
40
+ width: `${indicator.progress.value}%`,
41
+ height: `${props.height}px`,
42
+ opacity: indicator.isLoading.value ? 1 : 0,
43
+ background: props.color,
44
+ backgroundSize: `${100 / indicator.progress.value * 100}% auto`,
45
+ transition: "width 0.1s, height 0.4s, opacity 0.4s",
46
+ zIndex: 999999
47
+ }
48
+ }, slots);
49
+ }
50
+ });
51
+ function useLoadingIndicator(opts) {
52
+ const progress = ref(0);
53
+ const isLoading = ref(false);
54
+ const step = computed(() => 1e4 / opts.duration);
55
+ let _timer = null;
56
+ let _throttle = null;
57
+ function start() {
58
+ clear();
59
+ progress.value = 0;
60
+ isLoading.value = true;
61
+ if (opts.throttle) {
62
+ if (process.client) {
63
+ _throttle = setTimeout(_startTimer, opts.throttle);
64
+ }
65
+ } else {
66
+ _startTimer();
67
+ }
68
+ }
69
+ function finish() {
70
+ progress.value = 100;
71
+ _hide();
72
+ }
73
+ function clear() {
74
+ clearInterval(_timer);
75
+ clearTimeout(_throttle);
76
+ _timer = null;
77
+ _throttle = null;
78
+ }
79
+ function _increase(num) {
80
+ progress.value = Math.min(100, progress.value + num);
81
+ }
82
+ function _hide() {
83
+ clear();
84
+ if (process.client) {
85
+ setTimeout(() => {
86
+ isLoading.value = false;
87
+ setTimeout(() => {
88
+ progress.value = 0;
89
+ }, 400);
90
+ }, 500);
91
+ }
92
+ }
93
+ function _startTimer() {
94
+ if (process.client) {
95
+ _timer = setInterval(() => {
96
+ _increase(step.value);
97
+ }, 100);
98
+ }
99
+ }
100
+ return {
101
+ progress,
102
+ isLoading,
103
+ start,
104
+ finish,
105
+ clear
106
+ };
107
+ }
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <Suspense @resolve="onResolve">
3
+ <ErrorComponent k-if="error" :error="error" />
4
+ <AppComponent k-else />
5
+ </Suspense>
6
+ </template>
7
+
8
+ <script setup>
9
+ import { defineAsyncComponent, onErrorCaptured, provide } from 'kdu'
10
+ import { callWithDtwo, isDtwoError, showError, useError, useRoute, useDtwoApp } from '#app'
11
+ import AppComponent from '#build/app-component.mjs'
12
+
13
+ const ErrorComponent = defineAsyncComponent(() => import('#build/error-component.mjs').then(r => r.default || r))
14
+
15
+ const dtwoApp = useDtwoApp()
16
+ const onResolve = dtwoApp.deferHydration()
17
+
18
+ // Inject default route (outside of pages) as active route
19
+ provide('_route', useRoute())
20
+
21
+ // kdu:setup hook
22
+ const results = dtwoApp.hooks.callHookWith(hooks => hooks.map(hook => hook()), 'kdu:setup')
23
+ if (process.dev && results && results.some(i => i && 'then' in i)) {
24
+ console.error('[dtwo] Error in `kdu:setup`. Callbacks must be synchronous.')
25
+ }
26
+
27
+ // error handling
28
+ const error = useError()
29
+ onErrorCaptured((err, target, info) => {
30
+ dtwoApp.hooks.callHook('kdu:error', err, target, info).catch(hookError => console.error('[dtwo] Error in `kdu:error` hook', hookError))
31
+ if (process.server || (isDtwoError(err) && (err.fatal || err.unhandled))) {
32
+ callWithDtwo(dtwoApp, showError, [err])
33
+ }
34
+ })
35
+ </script>
@@ -0,0 +1,2 @@
1
+ export { defineDtwoLink } from './dtwo-link';
2
+ export type { DtwoLinkOptions, DtwoLinkProps } from './dtwo-link';
@@ -0,0 +1 @@
1
+ export { defineDtwoLink } from "./dtwo-link.mjs";
@@ -0,0 +1,17 @@
1
+ import { Ref, KNode } from 'kdu';
2
+ declare const _default: import("kdu").DefineComponent<{
3
+ name: {
4
+ type: () => string | false | Ref<string | false>;
5
+ default: null;
6
+ };
7
+ }, () => KNode<import("kdu").RendererNode, import("kdu").RendererElement, {
8
+ [key: string]: any;
9
+ }>, unknown, {}, {}, import("kdu").ComponentOptionsMixin, import("kdu").ComponentOptionsMixin, {}, string, import("kdu").KNodeProps & import("kdu").AllowedComponentProps & import("kdu").ComponentCustomProps, Readonly<import("kdu").ExtractPropTypes<{
10
+ name: {
11
+ type: () => string | false | Ref<string | false>;
12
+ default: null;
13
+ };
14
+ }>>, {
15
+ name: string | false | Ref<string | false>;
16
+ }>;
17
+ export default _default;
@@ -0,0 +1,66 @@
1
+ import { computed, defineComponent, h, inject, nextTick, onMounted, Transition, unref } from "kdu";
2
+ import { _wrapIf } from "./utils.mjs";
3
+ import { useRoute } from "#app";
4
+ import { useRoute as useKduRouterRoute } from "#build/pages";
5
+ import layouts from "#build/layouts";
6
+ import { appLayoutTransition as defaultLayoutTransition } from "#build/dtwo.config.mjs";
7
+ const LayoutLoader = defineComponent({
8
+ props: {
9
+ name: String,
10
+ ...process.dev ? { hasTransition: Boolean } : {}
11
+ },
12
+ async setup(props, context) {
13
+ let knode;
14
+ if (process.dev && process.client) {
15
+ onMounted(() => {
16
+ nextTick(() => {
17
+ if (props.name && ["#comment", "#text"].includes(knode?.el?.nodeName)) {
18
+ console.warn(`[dtwo] \`${props.name}\` layout does not have a single root node and will cause errors when navigating between routes.`);
19
+ }
20
+ });
21
+ });
22
+ }
23
+ const LayoutComponent = await layouts[props.name]().then((r) => r.default || r);
24
+ return () => {
25
+ if (process.dev && process.client && props.hasTransition) {
26
+ knode = h(LayoutComponent, {}, context.slots);
27
+ return knode;
28
+ }
29
+ return h(LayoutComponent, {}, context.slots);
30
+ };
31
+ }
32
+ });
33
+ export default defineComponent({
34
+ props: {
35
+ name: {
36
+ type: [String, Boolean, Object],
37
+ default: null
38
+ }
39
+ },
40
+ setup(props, context) {
41
+ const injectedRoute = inject("_route");
42
+ const route = injectedRoute === useRoute() ? useKduRouterRoute() : injectedRoute;
43
+ const layout = computed(() => unref(props.name) ?? route.meta.layout ?? "default");
44
+ let knode;
45
+ let _layout;
46
+ if (process.dev && process.client) {
47
+ onMounted(() => {
48
+ nextTick(() => {
49
+ if (_layout && _layout in layouts && ["#comment", "#text"].includes(knode?.el?.nodeName)) {
50
+ console.warn(`[dtwo] \`${_layout}\` layout does not have a single root node and will cause errors when navigating between routes.`);
51
+ }
52
+ });
53
+ });
54
+ }
55
+ return () => {
56
+ const hasLayout = layout.value && layout.value in layouts;
57
+ if (process.dev && layout.value && !hasLayout && layout.value !== "default") {
58
+ console.warn(`Invalid layout \`${layout.value}\` selected.`);
59
+ }
60
+ const transitionProps = route.meta.layoutTransition ?? defaultLayoutTransition;
61
+ return _wrapIf(Transition, hasLayout && transitionProps, {
62
+ default: () => _wrapIf(LayoutLoader, hasLayout && { key: layout.value, name: layout.value, hasTransition: process.dev ? !!transitionProps : void 0 }, context.slots).default()
63
+ }).default();
64
+ };
65
+ }
66
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("kdu").DefineComponent<{}, {}, {}, {}, {}, import("kdu").ComponentOptionsMixin, import("kdu").ComponentOptionsMixin, {}, string, import("kdu").KNodeProps & import("kdu").AllowedComponentProps & import("kdu").ComponentCustomProps, Readonly<import("kdu").ExtractPropTypes<{}>>, {}>;
2
+ export default _default;
@@ -0,0 +1,7 @@
1
+ import { defineComponent, createElementBlock } from "kdu";
2
+ export default defineComponent({
3
+ name: "ServerPlaceholder",
4
+ render() {
5
+ return createElementBlock("div");
6
+ }
7
+ });
@@ -0,0 +1,11 @@
1
+ import type { Component } from 'kdu';
2
+ /**
3
+ * Internal utility
4
+ *
5
+ * @private
6
+ */
7
+ export declare const _wrapIf: (component: Component, props: any, slots: any) => {
8
+ default: () => import("kdu").KNode<import("kdu").RendererNode, import("kdu").RendererElement, {
9
+ [key: string]: any;
10
+ }>;
11
+ };
@@ -0,0 +1,9 @@
1
+ import { defineComponent, h } from "kdu";
2
+ const Fragment = defineComponent({
3
+ setup(_props, { slots }) {
4
+ return () => slots.default?.();
5
+ }
6
+ });
7
+ export const _wrapIf = (component, props, slots) => {
8
+ return { default: () => props ? h(component, props === true ? {} : props, slots) : h(Fragment, {}, slots) };
9
+ };
@@ -0,0 +1,40 @@
1
+ import type { Ref, WatchSource } from 'kdu';
2
+ import { DtwoApp } from '../dtwo';
3
+ export type _Transform<Input = any, Output = any> = (input: Input) => Output;
4
+ export type PickFrom<T, K extends Array<string>> = T extends Array<any> ? T : T extends Record<string, any> ? keyof T extends K[number] ? T : Pick<T, K[number]> : T;
5
+ export type KeysOf<T> = Array<T extends T ? keyof T extends string ? keyof T : string : never>;
6
+ export type KeyOfRes<Transform extends _Transform> = KeysOf<ReturnType<Transform>>;
7
+ type MultiWatchSources = (WatchSource<unknown> | object)[];
8
+ export interface AsyncDataOptions<DataT, Transform extends _Transform<DataT, any> = _Transform<DataT, DataT>, PickKeys extends KeyOfRes<_Transform> = KeyOfRes<Transform>> {
9
+ server?: boolean;
10
+ lazy?: boolean;
11
+ default?: () => DataT | Ref<DataT> | null;
12
+ transform?: Transform;
13
+ pick?: PickKeys;
14
+ watch?: MultiWatchSources;
15
+ immediate?: boolean;
16
+ }
17
+ export interface AsyncDataExecuteOptions {
18
+ _initial?: boolean;
19
+ /**
20
+ * Force a refresh, even if there is already a pending request. Previous requests will
21
+ * not be cancelled, but their result will not affect the data/pending state - and any
22
+ * previously awaited promises will not resolve until this new request resolves.
23
+ */
24
+ dedupe?: boolean;
25
+ }
26
+ export interface _AsyncData<DataT, ErrorT> {
27
+ data: Ref<DataT | null>;
28
+ pending: Ref<boolean>;
29
+ refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>;
30
+ execute: (opts?: AsyncDataExecuteOptions) => Promise<void>;
31
+ error: Ref<ErrorT | null>;
32
+ }
33
+ export type AsyncData<Data, Error> = _AsyncData<Data, Error> & Promise<_AsyncData<Data, Error>>;
34
+ export declare function useAsyncData<DataT, DataE = Error, Transform extends _Transform<DataT> = _Transform<DataT, DataT>, PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>>(handler: (ctx?: DtwoApp) => Promise<DataT>, options?: AsyncDataOptions<DataT, Transform, PickKeys>): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE | null>;
35
+ export declare function useAsyncData<DataT, DataE = Error, Transform extends _Transform<DataT> = _Transform<DataT, DataT>, PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>>(key: string, handler: (ctx?: DtwoApp) => Promise<DataT>, options?: AsyncDataOptions<DataT, Transform, PickKeys>): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE | null>;
36
+ export declare function useLazyAsyncData<DataT, DataE = Error, Transform extends _Transform<DataT> = _Transform<DataT, DataT>, PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>>(handler: (ctx?: DtwoApp) => Promise<DataT>, options?: Omit<AsyncDataOptions<DataT, Transform, PickKeys>, 'lazy'>): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE | null>;
37
+ export declare function useLazyAsyncData<DataT, DataE = Error, Transform extends _Transform<DataT> = _Transform<DataT, DataT>, PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>>(key: string, handler: (ctx?: DtwoApp) => Promise<DataT>, options?: Omit<AsyncDataOptions<DataT, Transform, PickKeys>, 'lazy'>): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, DataE | null>;
38
+ export declare function refreshDtwoData(keys?: string | string[]): Promise<void>;
39
+ export declare function clearDtwoData(keys?: string | string[] | ((key: string) => boolean)): void;
40
+ export {};
@@ -0,0 +1,169 @@
1
+ import { onBeforeMount, onServerPrefetch, onUnmounted, ref, getCurrentInstance, watch, unref } from "kdu";
2
+ import { useDtwoApp } from "../dtwo.mjs";
3
+ import { createError } from "./error.mjs";
4
+ const getDefault = () => null;
5
+ export function useAsyncData(...args) {
6
+ const autoKey = typeof args[args.length - 1] === "string" ? args.pop() : void 0;
7
+ if (typeof args[0] !== "string") {
8
+ args.unshift(autoKey);
9
+ }
10
+ let [key, handler, options = {}] = args;
11
+ if (typeof key !== "string") {
12
+ throw new TypeError("[dtwo] [asyncData] key must be a string.");
13
+ }
14
+ if (typeof handler !== "function") {
15
+ throw new TypeError("[dtwo] [asyncData] handler must be a function.");
16
+ }
17
+ options.server = options.server ?? true;
18
+ options.default = options.default ?? getDefault;
19
+ options.lazy = options.lazy ?? false;
20
+ options.immediate = options.immediate ?? true;
21
+ const dtwo = useDtwoApp();
22
+ const getCachedData = () => dtwo.isHydrating ? dtwo.payload.data[key] : dtwo.static.data[key];
23
+ const hasCachedData = () => getCachedData() !== void 0;
24
+ if (!dtwo._asyncData[key]) {
25
+ dtwo._asyncData[key] = {
26
+ data: ref(getCachedData() ?? options.default?.() ?? null),
27
+ pending: ref(!hasCachedData()),
28
+ error: ref(dtwo.payload._errors[key] ? createError(dtwo.payload._errors[key]) : null)
29
+ };
30
+ }
31
+ const asyncData = { ...dtwo._asyncData[key] };
32
+ asyncData.refresh = asyncData.execute = (opts = {}) => {
33
+ if (dtwo._asyncDataPromises[key]) {
34
+ if (opts.dedupe === false) {
35
+ return dtwo._asyncDataPromises[key];
36
+ }
37
+ dtwo._asyncDataPromises[key].cancelled = true;
38
+ }
39
+ if (opts._initial && hasCachedData()) {
40
+ return getCachedData();
41
+ }
42
+ asyncData.pending.value = true;
43
+ const promise = new Promise(
44
+ (resolve, reject) => {
45
+ try {
46
+ resolve(handler(dtwo));
47
+ } catch (err) {
48
+ reject(err);
49
+ }
50
+ }
51
+ ).then((result) => {
52
+ if (promise.cancelled) {
53
+ return dtwo._asyncDataPromises[key];
54
+ }
55
+ if (options.transform) {
56
+ result = options.transform(result);
57
+ }
58
+ if (options.pick) {
59
+ result = pick(result, options.pick);
60
+ }
61
+ asyncData.data.value = result;
62
+ asyncData.error.value = null;
63
+ }).catch((error) => {
64
+ if (promise.cancelled) {
65
+ return dtwo._asyncDataPromises[key];
66
+ }
67
+ asyncData.error.value = error;
68
+ asyncData.data.value = unref(options.default?.() ?? null);
69
+ }).finally(() => {
70
+ if (promise.cancelled) {
71
+ return;
72
+ }
73
+ asyncData.pending.value = false;
74
+ dtwo.payload.data[key] = asyncData.data.value;
75
+ if (asyncData.error.value) {
76
+ dtwo.payload._errors[key] = createError(asyncData.error.value);
77
+ }
78
+ delete dtwo._asyncDataPromises[key];
79
+ });
80
+ dtwo._asyncDataPromises[key] = promise;
81
+ return dtwo._asyncDataPromises[key];
82
+ };
83
+ const initialFetch = () => asyncData.refresh({ _initial: true });
84
+ const fetchOnServer = options.server !== false && dtwo.payload.serverRendered;
85
+ if (process.server && fetchOnServer && options.immediate) {
86
+ const promise = initialFetch();
87
+ onServerPrefetch(() => promise);
88
+ }
89
+ if (process.client) {
90
+ const instance = getCurrentInstance();
91
+ if (instance && !instance._dtwoOnBeforeMountCbs) {
92
+ instance._dtwoOnBeforeMountCbs = [];
93
+ const cbs = instance._dtwoOnBeforeMountCbs;
94
+ if (instance) {
95
+ onBeforeMount(() => {
96
+ cbs.forEach((cb) => {
97
+ cb();
98
+ });
99
+ cbs.splice(0, cbs.length);
100
+ });
101
+ onUnmounted(() => cbs.splice(0, cbs.length));
102
+ }
103
+ }
104
+ if (fetchOnServer && dtwo.isHydrating && hasCachedData()) {
105
+ asyncData.pending.value = false;
106
+ } else if (instance && (dtwo.payload.serverRendered && dtwo.isHydrating || options.lazy) && options.immediate) {
107
+ instance._dtwoOnBeforeMountCbs.push(initialFetch);
108
+ } else if (options.immediate) {
109
+ initialFetch();
110
+ }
111
+ if (options.watch) {
112
+ watch(options.watch, () => asyncData.refresh());
113
+ }
114
+ const off = dtwo.hook("app:data:refresh", (keys) => {
115
+ if (!keys || keys.includes(key)) {
116
+ return asyncData.refresh();
117
+ }
118
+ });
119
+ if (instance) {
120
+ onUnmounted(off);
121
+ }
122
+ }
123
+ const asyncDataPromise = Promise.resolve(dtwo._asyncDataPromises[key]).then(() => asyncData);
124
+ Object.assign(asyncDataPromise, asyncData);
125
+ return asyncDataPromise;
126
+ }
127
+ export function useLazyAsyncData(...args) {
128
+ const autoKey = typeof args[args.length - 1] === "string" ? args.pop() : void 0;
129
+ if (typeof args[0] !== "string") {
130
+ args.unshift(autoKey);
131
+ }
132
+ const [key, handler, options] = args;
133
+ return useAsyncData(key, handler, { ...options, lazy: true }, null);
134
+ }
135
+ export async function refreshDtwoData(keys) {
136
+ if (process.server) {
137
+ return Promise.resolve();
138
+ }
139
+ const _keys = keys ? Array.isArray(keys) ? keys : [keys] : void 0;
140
+ await useDtwoApp().hooks.callHookParallel("app:data:refresh", _keys);
141
+ }
142
+ export function clearDtwoData(keys) {
143
+ const dtwoApp = useDtwoApp();
144
+ const _allKeys = Object.keys(dtwoApp.payload.data);
145
+ const _keys = !keys ? _allKeys : typeof keys === "function" ? _allKeys.filter(keys) : Array.isArray(keys) ? keys : [keys];
146
+ for (const key of _keys) {
147
+ if (key in dtwoApp.payload.data) {
148
+ dtwoApp.payload.data[key] = void 0;
149
+ }
150
+ if (key in dtwoApp.payload._errors) {
151
+ dtwoApp.payload._errors[key] = void 0;
152
+ }
153
+ if (dtwoApp._asyncData[key]) {
154
+ dtwoApp._asyncData[key].data.value = void 0;
155
+ dtwoApp._asyncData[key].error.value = void 0;
156
+ dtwoApp._asyncData[key].pending.value = false;
157
+ }
158
+ if (key in dtwoApp._asyncDataPromises) {
159
+ dtwoApp._asyncDataPromises[key] = void 0;
160
+ }
161
+ }
162
+ }
163
+ function pick(obj, keys) {
164
+ const newObj = {};
165
+ for (const key of keys) {
166
+ newObj[key] = obj[key];
167
+ }
168
+ return newObj;
169
+ }
@@ -0,0 +1,3 @@
1
+ import { defineComponent } from 'kdu';
2
+ export declare const DtwoComponentIndicator = "__dtwo_component";
3
+ export declare const defineDtwoComponent: typeof defineComponent;
@@ -0,0 +1,46 @@
1
+ import { getCurrentInstance, reactive, toRefs } from "kdu";
2
+ import { useDtwoApp } from "../dtwo.mjs";
3
+ import { useAsyncData } from "./asyncData.mjs";
4
+ import { useRoute } from "./router.mjs";
5
+ import { useHead } from "#head";
6
+ export const DtwoComponentIndicator = "__dtwo_component";
7
+ async function runLegacyAsyncData(res, fn) {
8
+ const dtwo = useDtwoApp();
9
+ const route = useRoute();
10
+ const vm = getCurrentInstance();
11
+ const { fetchKey } = vm.proxy.$options;
12
+ const key = typeof fetchKey === "function" ? fetchKey(() => "") : fetchKey || route.fullPath;
13
+ const { data } = await useAsyncData(`options:asyncdata:${key}`, () => fn(dtwo));
14
+ if (data.value && typeof data.value === "object") {
15
+ Object.assign(await res, toRefs(reactive(data.value)));
16
+ } else if (process.dev) {
17
+ console.warn("[dtwo] asyncData should return an object", data);
18
+ }
19
+ }
20
+ export const defineDtwoComponent = function defineDtwoComponent2(options) {
21
+ const { setup } = options;
22
+ if (!setup && !options.asyncData && !options.head) {
23
+ return {
24
+ [DtwoComponentIndicator]: true,
25
+ ...options
26
+ };
27
+ }
28
+ return {
29
+ [DtwoComponentIndicator]: true,
30
+ ...options,
31
+ setup(props, ctx) {
32
+ const res = setup?.(props, ctx) || {};
33
+ const promises = [];
34
+ if (options.asyncData) {
35
+ promises.push(runLegacyAsyncData(res, options.asyncData));
36
+ }
37
+ if (options.head) {
38
+ const dtwoApp = useDtwoApp();
39
+ useHead(typeof options.head === "function" ? () => options.head(dtwoApp) : options.head);
40
+ }
41
+ return Promise.resolve(res).then(() => Promise.all(promises)).then(() => res).finally(() => {
42
+ promises.length = 0;
43
+ });
44
+ }
45
+ };
46
+ };
@@ -0,0 +1,12 @@
1
+ import { Ref } from 'kdu';
2
+ import { CookieParseOptions, CookieSerializeOptions } from 'cookie-es';
3
+ type _CookieOptions = Omit<CookieSerializeOptions & CookieParseOptions, 'decode' | 'encode'>;
4
+ export interface CookieOptions<T = any> extends _CookieOptions {
5
+ decode?(value: string): T;
6
+ encode?(value: T): string;
7
+ default?: () => T | Ref<T>;
8
+ }
9
+ export interface CookieRef<T> extends Ref<T | null> {
10
+ }
11
+ export declare function useCookie<T = string>(name: string, _opts?: CookieOptions<T>): CookieRef<T>;
12
+ export {};
@@ -0,0 +1,58 @@
1
+ import { ref, watch } from "kdu";
2
+ import { parse, serialize } from "cookie-es";
3
+ import { appendHeader } from "h3";
4
+ import destr from "destr";
5
+ import { isEqual } from "ohash";
6
+ import { useDtwoApp } from "../dtwo.mjs";
7
+ import { useRequestEvent } from "./ssr.mjs";
8
+ const CookieDefaults = {
9
+ path: "/",
10
+ decode: (val) => destr(decodeURIComponent(val)),
11
+ encode: (val) => encodeURIComponent(typeof val === "string" ? val : JSON.stringify(val))
12
+ };
13
+ export function useCookie(name, _opts) {
14
+ const opts = { ...CookieDefaults, ..._opts };
15
+ const cookies = readRawCookies(opts) || {};
16
+ const cookie = ref(cookies[name] ?? opts.default?.());
17
+ if (process.client) {
18
+ watch(cookie, () => {
19
+ writeClientCookie(name, cookie.value, opts);
20
+ });
21
+ } else if (process.server) {
22
+ const dtwoApp = useDtwoApp();
23
+ const writeFinalCookieValue = () => {
24
+ if (!isEqual(cookie.value, cookies[name])) {
25
+ writeServerCookie(useRequestEvent(dtwoApp), name, cookie.value, opts);
26
+ }
27
+ };
28
+ const unhook = dtwoApp.hooks.hookOnce("app:rendered", writeFinalCookieValue);
29
+ dtwoApp.hooks.hookOnce("app:redirected", () => {
30
+ unhook();
31
+ return writeFinalCookieValue();
32
+ });
33
+ }
34
+ return cookie;
35
+ }
36
+ function readRawCookies(opts = {}) {
37
+ if (process.server) {
38
+ return parse(useRequestEvent()?.req.headers.cookie || "", opts);
39
+ } else if (process.client) {
40
+ return parse(document.cookie, opts);
41
+ }
42
+ }
43
+ function serializeCookie(name, value, opts = {}) {
44
+ if (value === null || value === void 0) {
45
+ return serialize(name, value, { ...opts, maxAge: -1 });
46
+ }
47
+ return serialize(name, value, opts);
48
+ }
49
+ function writeClientCookie(name, value, opts = {}) {
50
+ if (process.client) {
51
+ document.cookie = serializeCookie(name, value, opts);
52
+ }
53
+ }
54
+ function writeServerCookie(event, name, value, opts = {}) {
55
+ if (event) {
56
+ appendHeader(event, "Set-Cookie", serializeCookie(name, value, opts));
57
+ }
58
+ }
@@ -0,0 +1,17 @@
1
+ import { H3Error } from 'h3';
2
+ export declare const useError: () => import("kdu").Ref<Error | {
3
+ url: string;
4
+ statusCode: string;
5
+ statusMessage: string;
6
+ message: string;
7
+ description: string;
8
+ data?: any;
9
+ } | null | undefined>;
10
+ export interface DtwoError extends H3Error {
11
+ }
12
+ export declare const showError: (_err: string | Error | Partial<DtwoError>) => DtwoError;
13
+ export declare const clearError: (options?: {
14
+ redirect?: string;
15
+ }) => Promise<void>;
16
+ export declare const isDtwoError: (err?: string | object) => err is DtwoError;
17
+ export declare const createError: (err: string | Partial<DtwoError>) => DtwoError;
@@ -0,0 +1,31 @@
1
+ import { createError as _createError } from "h3";
2
+ import { toRef } from "kdu";
3
+ import { useDtwoApp } from "../dtwo.mjs";
4
+ export const useError = () => toRef(useDtwoApp().payload, "error");
5
+ export const showError = (_err) => {
6
+ const err = createError(_err);
7
+ try {
8
+ const dtwoApp = useDtwoApp();
9
+ dtwoApp.callHook("app:error", err);
10
+ const error = useError();
11
+ error.value = error.value || err;
12
+ } catch {
13
+ throw err;
14
+ }
15
+ return err;
16
+ };
17
+ export const clearError = async (options = {}) => {
18
+ const dtwoApp = useDtwoApp();
19
+ const error = useError();
20
+ dtwoApp.callHook("app:error:cleared", options);
21
+ if (options.redirect) {
22
+ await dtwoApp.$router.replace(options.redirect);
23
+ }
24
+ error.value = null;
25
+ };
26
+ export const isDtwoError = (err) => !!(err && typeof err === "object" && "__dtwo_error" in err);
27
+ export const createError = (err) => {
28
+ const _err = _createError(err);
29
+ _err.__dtwo_error = true;
30
+ return _err;
31
+ };
@@ -0,0 +1,15 @@
1
+ import type { FetchError, FetchOptions } from 'ofetch';
2
+ import type { TypedInternalResponse, HoleFetchRequest } from 'holepack';
3
+ import { Ref } from 'kdu';
4
+ import type { AsyncDataOptions, _Transform, KeyOfRes, AsyncData, PickFrom } from './asyncData';
5
+ export type FetchResult<ReqT extends HoleFetchRequest> = TypedInternalResponse<ReqT, unknown>;
6
+ type ComputedOptions<T extends Record<string, any>> = {
7
+ [K in keyof T]: T[K] extends Function ? T[K] : T[K] extends Record<string, any> ? ComputedOptions<T[K]> | Ref<T[K]> | T[K] : Ref<T[K]> | T[K];
8
+ };
9
+ type ComputedFetchOptions = ComputedOptions<FetchOptions>;
10
+ export interface UseFetchOptions<DataT, Transform extends _Transform<DataT, any> = _Transform<DataT, DataT>, PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>> extends AsyncDataOptions<DataT, Transform, PickKeys>, ComputedFetchOptions {
11
+ key?: string;
12
+ }
13
+ export declare function useFetch<ResT = void, ErrorT = FetchError, ReqT extends HoleFetchRequest = HoleFetchRequest, _ResT = ResT extends void ? FetchResult<ReqT> : ResT, Transform extends (res: _ResT) => any = (res: _ResT) => _ResT, PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>>(request: Ref<ReqT> | ReqT | (() => ReqT), opts?: UseFetchOptions<_ResT, Transform, PickKeys>): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, ErrorT | null>;
14
+ export declare function useLazyFetch<ResT = void, ErrorT = FetchError, ReqT extends HoleFetchRequest = HoleFetchRequest, _ResT = ResT extends void ? FetchResult<ReqT> : ResT, Transform extends (res: _ResT) => any = (res: _ResT) => _ResT, PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>>(request: Ref<ReqT> | ReqT | (() => ReqT), opts?: Omit<UseFetchOptions<_ResT, Transform, PickKeys>, 'lazy'>): AsyncData<PickFrom<ReturnType<Transform>, PickKeys>, ErrorT | null>;
15
+ export {};