@typed/navigation 0.1.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.
- package/dist/DOM.d.ts +12 -0
- package/dist/DOM.d.ts.map +1 -0
- package/dist/DOM.js +89 -0
- package/dist/DOM.js.map +1 -0
- package/dist/Memory.d.ts +10 -0
- package/dist/Memory.d.ts.map +1 -0
- package/dist/Memory.js +55 -0
- package/dist/Memory.js.map +1 -0
- package/dist/Navigation.d.ts +117 -0
- package/dist/Navigation.d.ts.map +1 -0
- package/dist/Navigation.js +36 -0
- package/dist/Navigation.js.map +1 -0
- package/dist/_makeServerWindow.d.ts +16 -0
- package/dist/_makeServerWindow.d.ts.map +1 -0
- package/dist/_makeServerWindow.js +9 -0
- package/dist/_makeServerWindow.js.map +1 -0
- package/dist/cjs/DOM.d.ts +12 -0
- package/dist/cjs/DOM.d.ts.map +1 -0
- package/dist/cjs/DOM.js +118 -0
- package/dist/cjs/DOM.js.map +1 -0
- package/dist/cjs/Memory.d.ts +10 -0
- package/dist/cjs/Memory.d.ts.map +1 -0
- package/dist/cjs/Memory.js +82 -0
- package/dist/cjs/Memory.js.map +1 -0
- package/dist/cjs/Navigation.d.ts +117 -0
- package/dist/cjs/Navigation.d.ts.map +1 -0
- package/dist/cjs/Navigation.js +69 -0
- package/dist/cjs/Navigation.js.map +1 -0
- package/dist/cjs/_makeServerWindow.d.ts +16 -0
- package/dist/cjs/_makeServerWindow.d.ts.map +1 -0
- package/dist/cjs/_makeServerWindow.js +36 -0
- package/dist/cjs/_makeServerWindow.js.map +1 -0
- package/dist/cjs/constant.d.ts +2 -0
- package/dist/cjs/constant.d.ts.map +1 -0
- package/dist/cjs/constant.js +30 -0
- package/dist/cjs/constant.js.map +1 -0
- package/dist/cjs/dom-intent.d.ts +29 -0
- package/dist/cjs/dom-intent.d.ts.map +1 -0
- package/dist/cjs/dom-intent.js +173 -0
- package/dist/cjs/dom-intent.js.map +1 -0
- package/dist/cjs/history.d.ts +31 -0
- package/dist/cjs/history.d.ts.map +1 -0
- package/dist/cjs/history.js +115 -0
- package/dist/cjs/history.js.map +1 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +20 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/json.d.ts +13 -0
- package/dist/cjs/json.d.ts.map +1 -0
- package/dist/cjs/json.js +24 -0
- package/dist/cjs/json.js.map +1 -0
- package/dist/cjs/memory-intent.d.ts +28 -0
- package/dist/cjs/memory-intent.d.ts.map +1 -0
- package/dist/cjs/memory-intent.js +149 -0
- package/dist/cjs/memory-intent.js.map +1 -0
- package/dist/cjs/model.d.ts +22 -0
- package/dist/cjs/model.d.ts.map +1 -0
- package/dist/cjs/model.js +48 -0
- package/dist/cjs/model.js.map +1 -0
- package/dist/cjs/shared-intent.d.ts +15 -0
- package/dist/cjs/shared-intent.d.ts.map +1 -0
- package/dist/cjs/shared-intent.js +82 -0
- package/dist/cjs/shared-intent.js.map +1 -0
- package/dist/cjs/storage.d.ts +19 -0
- package/dist/cjs/storage.d.ts.map +1 -0
- package/dist/cjs/storage.js +101 -0
- package/dist/cjs/storage.js.map +1 -0
- package/dist/cjs/util.d.ts +5 -0
- package/dist/cjs/util.d.ts.map +1 -0
- package/dist/cjs/util.js +39 -0
- package/dist/cjs/util.js.map +1 -0
- package/dist/constant.d.ts +2 -0
- package/dist/constant.d.ts.map +1 -0
- package/dist/constant.js +4 -0
- package/dist/constant.js.map +1 -0
- package/dist/dom-intent.d.ts +29 -0
- package/dist/dom-intent.d.ts.map +1 -0
- package/dist/dom-intent.js +141 -0
- package/dist/dom-intent.js.map +1 -0
- package/dist/history.d.ts +31 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +88 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/intent.d.ts +31 -0
- package/dist/intent.d.ts.map +1 -0
- package/dist/intent.js +157 -0
- package/dist/intent.js.map +1 -0
- package/dist/json.d.ts +13 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +17 -0
- package/dist/json.js.map +1 -0
- package/dist/memory-intent.d.ts +28 -0
- package/dist/memory-intent.d.ts.map +1 -0
- package/dist/memory-intent.js +117 -0
- package/dist/memory-intent.js.map +1 -0
- package/dist/model.d.ts +22 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +21 -0
- package/dist/model.js.map +1 -0
- package/dist/shared-intent.d.ts +15 -0
- package/dist/shared-intent.d.ts.map +1 -0
- package/dist/shared-intent.js +51 -0
- package/dist/shared-intent.js.map +1 -0
- package/dist/storage.d.ts +19 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +73 -0
- package/dist/storage.js.map +1 -0
- package/dist/tsconfig.cjs.build.tsbuildinfo +1 -0
- package/dist/util.d.ts +5 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +12 -0
- package/dist/util.js.map +1 -0
- package/eslintrc.json +3 -0
- package/package.json +38 -0
- package/project.json +43 -0
- package/src/DOM.test.ts +704 -0
- package/src/DOM.ts +165 -0
- package/src/Memory.test.ts +464 -0
- package/src/Memory.ts +102 -0
- package/src/Navigation.ts +192 -0
- package/src/_makeServerWindow.ts +28 -0
- package/src/constant.ts +5 -0
- package/src/dom-intent.ts +276 -0
- package/src/history.ts +141 -0
- package/src/index.ts +3 -0
- package/src/json.ts +31 -0
- package/src/memory-intent.ts +221 -0
- package/src/model.ts +54 -0
- package/src/shared-intent.ts +120 -0
- package/src/storage.ts +101 -0
- package/src/util.ts +20 -0
- package/tsconfig.build.json +4 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.cjs.build.json +22 -0
- package/tsconfig.json +27 -0
- package/vite.config.js +3 -0
package/dist/DOM.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as Layer from '@effect/io/Layer';
|
|
2
|
+
import { Location, History, Window, Storage, Document } from '@typed/dom';
|
|
3
|
+
import { DestinationKey, Navigation } from './Navigation.js';
|
|
4
|
+
export type NavigationServices = Window | Document | Location | History | Storage;
|
|
5
|
+
export interface DomNavigationOptions {
|
|
6
|
+
readonly initialKey?: DestinationKey;
|
|
7
|
+
readonly maxEntries?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare const dom: (options?: DomNavigationOptions) => Layer.Layer<NavigationServices, never, Navigation>;
|
|
10
|
+
export declare function getBasePathFromHref(href: string): string;
|
|
11
|
+
export declare function getCurrentPathFromLocation(location: Location | HTMLAnchorElement | URL): string;
|
|
12
|
+
//# sourceMappingURL=DOM.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DOM.d.ts","sourceRoot":"","sources":["../src/DOM.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA;AAEzC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAqB,QAAQ,EAAE,MAAM,YAAY,CAAA;AAG5F,OAAO,EAAe,cAAc,EAAE,UAAU,EAAmB,MAAM,iBAAiB,CAAA;AAO1F,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAA;AAEjF,MAAM,WAAW,oBAAoB;IAGnC,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,CAAA;IAIpC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,eAAO,MAAM,GAAG,aACL,oBAAoB,KAC5B,WAAW,CAAC,kBAAkB,EAAE,KAAK,EAAE,UAAU,CAwHnD,CAAA;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,UAQ/C;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,QAAQ,GAAG,iBAAiB,GAAG,GAAG,UAEtF"}
|
package/dist/DOM.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { pipe } from '@effect/data/Function';
|
|
2
|
+
import * as Option from '@effect/data/Option';
|
|
3
|
+
import * as Effect from '@effect/io/Effect';
|
|
4
|
+
import * as Context from '@typed/context';
|
|
5
|
+
import { History, addWindowListener, Document } from '@typed/dom';
|
|
6
|
+
import * as Fx from '@typed/fx';
|
|
7
|
+
import { Navigation } from './Navigation.js';
|
|
8
|
+
import { makeIntent } from './dom-intent.js';
|
|
9
|
+
import { onHistoryEvent, patchHistory } from './history.js';
|
|
10
|
+
import { makeModel } from './model.js';
|
|
11
|
+
import { getInitialValues } from './storage.js';
|
|
12
|
+
export const dom = (options = {}) => {
|
|
13
|
+
return Navigation.layerScoped(Effect.gen(function* ($) {
|
|
14
|
+
// Get resources
|
|
15
|
+
const context = yield* $(Effect.context());
|
|
16
|
+
const history = Context.get(context, History);
|
|
17
|
+
const document = Context.get(context, Document);
|
|
18
|
+
const base = document.querySelector('base');
|
|
19
|
+
const baseHref = base ? getBasePathFromHref(base.href) : '/';
|
|
20
|
+
// Create model and intent
|
|
21
|
+
const [initialEntries, initialIndex] = yield* $(getInitialValues(baseHref, options));
|
|
22
|
+
const model = yield* $(makeModel(initialEntries, initialIndex));
|
|
23
|
+
const intent = makeIntent(model, baseHref, options);
|
|
24
|
+
// Used to ensure ordering of navigation events
|
|
25
|
+
const lock = Effect.unsafeMakeSemaphore(1).withPermits(1);
|
|
26
|
+
const handleNavigationError = (depth) => (error) => Effect.provideContext(Effect.gen(function* ($) {
|
|
27
|
+
if (depth >= 50) {
|
|
28
|
+
throw new Error('Too many redirects. You may have an infinite loop of onNavigation handlers that are redirecting.');
|
|
29
|
+
}
|
|
30
|
+
switch (error._tag) {
|
|
31
|
+
case 'NoSuchElementException':
|
|
32
|
+
case 'CancelNavigation':
|
|
33
|
+
return yield* $(model.currentEntry.get);
|
|
34
|
+
case 'RedirectNavigation':
|
|
35
|
+
return yield* $(Effect.catchAll(intent.navigate(error.url, error), handleNavigationError(depth + 1)));
|
|
36
|
+
}
|
|
37
|
+
}), context);
|
|
38
|
+
const catchNavigationError = (effect) => Effect.catchAll(effect, handleNavigationError(0));
|
|
39
|
+
// Used to provide a locked effect with the current context
|
|
40
|
+
const provideLocked = (effect) => Effect.provideContext(lock(effect), context);
|
|
41
|
+
// Constructor our service
|
|
42
|
+
const navigation = {
|
|
43
|
+
back: provideLocked(catchNavigationError(intent.back(false))),
|
|
44
|
+
base: baseHref,
|
|
45
|
+
canGoBack: model.canGoBack,
|
|
46
|
+
canGoForward: model.canGoForward,
|
|
47
|
+
currentEntry: model.currentEntry,
|
|
48
|
+
entries: model.entries,
|
|
49
|
+
forward: provideLocked(catchNavigationError(intent.forward(false))),
|
|
50
|
+
goTo: (a) => pipe(a, intent.goTo, Effect.catchAll((a) => pipe(a, handleNavigationError(0), Effect.map(Option.some))), provideLocked),
|
|
51
|
+
navigate: (url, options) => pipe(intent.navigate(url, options), catchNavigationError, provideLocked),
|
|
52
|
+
onNavigation: (handler, options) => pipe(intent.onNavigation(handler, options), catchNavigationError, Effect.asUnit),
|
|
53
|
+
onNavigationEnd: (handler, options) => Effect.asUnit(intent.onNavigationEnd(handler, options)),
|
|
54
|
+
reload: provideLocked(catchNavigationError(intent.reload)),
|
|
55
|
+
};
|
|
56
|
+
// Patch History API to enable sending events
|
|
57
|
+
const historyEvents = yield* $(patchHistory);
|
|
58
|
+
// Listen to various events and update our model
|
|
59
|
+
yield* $(Fx.mergeAll(
|
|
60
|
+
// Listen to history events and keep track of entries
|
|
61
|
+
pipe(historyEvents, Fx.flatMapEffect((event) => lock(onHistoryEvent(event, intent)))),
|
|
62
|
+
// Listen to hash changes and push them to the history
|
|
63
|
+
pipe(addWindowListener('hashchange', { capture: true }), Fx.flatMapEffect((ev) => lock(intent.push(ev.newURL, { state: history.state }, true)))),
|
|
64
|
+
// Listen to popstate events and go to the correct entry
|
|
65
|
+
pipe(addWindowListener('popstate'), Fx.map((ev) => {
|
|
66
|
+
// TODO: Should we throw some kind of error here?
|
|
67
|
+
// This should never happen if you are solely using the Navigation Service
|
|
68
|
+
if (!ev.state || !ev.state.event) {
|
|
69
|
+
return Option.none();
|
|
70
|
+
}
|
|
71
|
+
const navigation = ev.state.event;
|
|
72
|
+
return Option.some(lock(intent.goTo(navigation.destination.key)));
|
|
73
|
+
}), Fx.compact, Fx.flattenEffect)), Fx.drain, Effect.forkScoped);
|
|
74
|
+
return navigation;
|
|
75
|
+
}));
|
|
76
|
+
};
|
|
77
|
+
export function getBasePathFromHref(href) {
|
|
78
|
+
try {
|
|
79
|
+
const url = new URL(href);
|
|
80
|
+
return getCurrentPathFromLocation(url);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return href;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export function getCurrentPathFromLocation(location) {
|
|
87
|
+
return location.pathname + location.search + location.hash;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=DOM.js.map
|
package/dist/DOM.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DOM.js","sourceRoot":"","sources":["../src/DOM.ts"],"names":[],"mappings":"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"}
|
package/dist/Memory.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as Layer from '@effect/io/Layer';
|
|
2
|
+
import type { DomNavigationOptions } from './DOM.js';
|
|
3
|
+
import { Navigation } from './Navigation.js';
|
|
4
|
+
export interface MemoryNavigationOptions extends DomNavigationOptions {
|
|
5
|
+
readonly initialUrl: URL;
|
|
6
|
+
readonly initialState?: unknown;
|
|
7
|
+
readonly base?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function memory(options: MemoryNavigationOptions): Layer.Layer<never, never, Navigation>;
|
|
10
|
+
//# sourceMappingURL=Memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Memory.d.ts","sourceRoot":"","sources":["../src/Memory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA;AAEzC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AACpD,OAAO,EAEL,UAAU,EAIX,MAAM,iBAAiB,CAAA;AAKxB,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACnE,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAA;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,uBAAuB,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CA6E9F"}
|
package/dist/Memory.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { pipe } from '@effect/data/Function';
|
|
2
|
+
import * as Option from '@effect/data/Option';
|
|
3
|
+
import * as Effect from '@effect/io/Effect';
|
|
4
|
+
import { Navigation, NavigationType, } from './Navigation.js';
|
|
5
|
+
import { makeIntent } from './memory-intent.js';
|
|
6
|
+
import { makeModel } from './model.js';
|
|
7
|
+
import { createKey } from './util.js';
|
|
8
|
+
export function memory(options) {
|
|
9
|
+
return Navigation.layerScoped(Effect.gen(function* ($) {
|
|
10
|
+
const initial = {
|
|
11
|
+
key: options.initialKey ?? (yield* $(createKey)),
|
|
12
|
+
url: options.initialUrl,
|
|
13
|
+
state: options.initialState,
|
|
14
|
+
};
|
|
15
|
+
const initialEvent = {
|
|
16
|
+
destination: initial,
|
|
17
|
+
hashChange: false,
|
|
18
|
+
navigationType: NavigationType.Push,
|
|
19
|
+
};
|
|
20
|
+
const model = yield* $(makeModel([initialEvent], 0));
|
|
21
|
+
const intent = makeIntent(model, options);
|
|
22
|
+
// Used to ensure ordering of navigation events
|
|
23
|
+
const lock = Effect.unsafeMakeSemaphore(1).withPermits(1);
|
|
24
|
+
const handleNavigationError = (depth) => (error) => Effect.gen(function* ($) {
|
|
25
|
+
if (depth >= 50) {
|
|
26
|
+
throw new Error('Too many redirects. You may have an infinite loop of onNavigation handlers that are redirecting.');
|
|
27
|
+
}
|
|
28
|
+
switch (error._tag) {
|
|
29
|
+
case 'NoSuchElementException':
|
|
30
|
+
case 'CancelNavigation':
|
|
31
|
+
return yield* $(model.currentEntry.get);
|
|
32
|
+
case 'RedirectNavigation':
|
|
33
|
+
return yield* $(Effect.catchAll(intent.navigate(error.url, error), handleNavigationError(depth + 1)));
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const catchNavigationError = (effect) => Effect.catchAll(effect, handleNavigationError(0));
|
|
37
|
+
// Construct our service
|
|
38
|
+
const navigation = {
|
|
39
|
+
back: lock(catchNavigationError(intent.back)),
|
|
40
|
+
base: '/',
|
|
41
|
+
canGoBack: model.canGoBack,
|
|
42
|
+
canGoForward: model.canGoForward,
|
|
43
|
+
currentEntry: model.currentEntry,
|
|
44
|
+
entries: model.entries,
|
|
45
|
+
forward: lock(catchNavigationError(intent.forward)),
|
|
46
|
+
goTo: (n) => pipe(n, intent.goTo, Effect.catchAll((a) => pipe(a, handleNavigationError(0), Effect.map(Option.some))), lock),
|
|
47
|
+
navigate: (url, options) => pipe(intent.navigate(url, options), catchNavigationError, lock),
|
|
48
|
+
onNavigation: (handler, options) => pipe(intent.onNavigation(handler, options), catchNavigationError, Effect.asUnit),
|
|
49
|
+
onNavigationEnd: (handler, options) => Effect.asUnit(intent.onNavigationEnd(handler, options)),
|
|
50
|
+
reload: lock(catchNavigationError(intent.reload)),
|
|
51
|
+
};
|
|
52
|
+
return navigation;
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=Memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Memory.js","sourceRoot":"","sources":["../src/Memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as Brand from '@effect/data/Brand';
|
|
2
|
+
import { Option } from '@effect/data/Option';
|
|
3
|
+
import * as Cause from '@effect/io/Cause';
|
|
4
|
+
import * as Effect from '@effect/io/Effect';
|
|
5
|
+
import * as Scope from '@effect/io/Scope';
|
|
6
|
+
import * as Context from '@typed/context';
|
|
7
|
+
import * as Fx from '@typed/fx';
|
|
8
|
+
export interface Navigation {
|
|
9
|
+
/**
|
|
10
|
+
* Base path for all navigation entries.
|
|
11
|
+
*/
|
|
12
|
+
readonly base: string;
|
|
13
|
+
/**
|
|
14
|
+
* The list of navigation entries that are currently kept in-memory and
|
|
15
|
+
* saved within Local/Session Storage.
|
|
16
|
+
*/
|
|
17
|
+
readonly entries: Fx.Computed<never, never, readonly Destination[]>;
|
|
18
|
+
/**
|
|
19
|
+
* The currently focused navigation entry.
|
|
20
|
+
*/
|
|
21
|
+
readonly currentEntry: Fx.Computed<never, never, Destination>;
|
|
22
|
+
/**
|
|
23
|
+
* Navigate to a new URL. NavigateOptions can be used to control how the
|
|
24
|
+
* navigation is handled via history.pushState or history.replaceState,
|
|
25
|
+
* set/update the state of the navigation entry, or provide a key to use
|
|
26
|
+
* for the navigation entry.
|
|
27
|
+
*/
|
|
28
|
+
readonly navigate: (url: string, options?: NavigateOptions) => Effect.Effect<never, never, Destination>;
|
|
29
|
+
/**
|
|
30
|
+
* Subscribe to navigation events. Any handler can cancel the or redirect
|
|
31
|
+
* the navigation by failing with a CancelNavigation or RedirectNavigation
|
|
32
|
+
* error.
|
|
33
|
+
*/
|
|
34
|
+
readonly onNavigation: <R>(handler: (event: NavigationEvent) => Effect.Effect<R, NavigationError, void>, options?: OnNavigationOptions) => Effect.Effect<R | Scope.Scope, never, void>;
|
|
35
|
+
/**
|
|
36
|
+
* Subscribe to navigation events after they have been commited.
|
|
37
|
+
*/
|
|
38
|
+
readonly onNavigationEnd: <R>(handler: (event: NavigationEvent) => Effect.Effect<R, never, void>, options?: OnNavigationOptions) => Effect.Effect<R | Scope.Scope, never, void>;
|
|
39
|
+
/**
|
|
40
|
+
* Returns true if there is a previous navigation entry to navigate to.
|
|
41
|
+
*/
|
|
42
|
+
readonly canGoBack: Fx.Computed<never, never, boolean>;
|
|
43
|
+
/**
|
|
44
|
+
* Navigate to the previous navigation entry. If you're on the first entry
|
|
45
|
+
* then this will do nothing.
|
|
46
|
+
*/
|
|
47
|
+
readonly back: Effect.Effect<never, never, Destination>;
|
|
48
|
+
/**
|
|
49
|
+
* Returns true if there is a next navigation entry to navigate to after you have gone back.
|
|
50
|
+
*/
|
|
51
|
+
readonly canGoForward: Fx.Computed<never, never, boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* Navigate to the next navigation entry. If you're on the last entry then
|
|
54
|
+
* this will do nothing.
|
|
55
|
+
*/
|
|
56
|
+
readonly forward: Effect.Effect<never, never, Destination>;
|
|
57
|
+
/**
|
|
58
|
+
* Reload the current navigation entry.
|
|
59
|
+
*/
|
|
60
|
+
readonly reload: Effect.Effect<never, never, Destination>;
|
|
61
|
+
/**
|
|
62
|
+
* Navigate to a specific navigation entry by key. If the key does not
|
|
63
|
+
* exist then this will do nothing visible to the user and return Option.none().
|
|
64
|
+
*/
|
|
65
|
+
readonly goTo: (key: DestinationKey) => Effect.Effect<never, never, Option<Destination>>;
|
|
66
|
+
}
|
|
67
|
+
export declare const Navigation: Context.Tag<Navigation, Navigation>;
|
|
68
|
+
export declare const navigate: (url: string, options?: NavigateOptions) => Effect.Effect<Navigation, never, Destination>;
|
|
69
|
+
export declare const onNavigation: <R>(handler: (event: NavigationEvent) => Effect.Effect<R, never, void>) => Effect.Effect<Scope.Scope | Navigation | R, never, void>;
|
|
70
|
+
export declare const canGoBack: Effect.Effect<Navigation, Cause.NoSuchElementException, boolean> & Fx.Fx<Navigation, never, boolean>;
|
|
71
|
+
export declare const back: Effect.Effect<Navigation, never, Destination>;
|
|
72
|
+
export declare const canGoForward: Effect.Effect<Navigation, Cause.NoSuchElementException, boolean> & Fx.Fx<Navigation, never, boolean>;
|
|
73
|
+
export declare const forward: Effect.Effect<Navigation, never, Destination>;
|
|
74
|
+
export declare const reload: Effect.Effect<Navigation, never, Destination>;
|
|
75
|
+
export interface NavigateOptions {
|
|
76
|
+
readonly state?: unknown;
|
|
77
|
+
readonly history?: 'push' | 'replace';
|
|
78
|
+
readonly key?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface NavigationEvent {
|
|
81
|
+
readonly destination: Destination;
|
|
82
|
+
readonly hashChange: boolean;
|
|
83
|
+
readonly navigationType: NavigationType;
|
|
84
|
+
}
|
|
85
|
+
export declare function NavigationEvent(destination: Destination, hashChange: boolean, navigationType: NavigationType): NavigationEvent;
|
|
86
|
+
export interface Destination {
|
|
87
|
+
readonly key: DestinationKey;
|
|
88
|
+
readonly url: URL;
|
|
89
|
+
readonly state: unknown;
|
|
90
|
+
}
|
|
91
|
+
export type DestinationKey = string & Brand.Brand<'DestinationKey'>;
|
|
92
|
+
export declare const DestinationKey: Brand.Brand.Constructor<DestinationKey>;
|
|
93
|
+
export declare function Destination(key: DestinationKey, url: URL, state?: unknown): Destination;
|
|
94
|
+
export declare enum NavigationType {
|
|
95
|
+
Push = "push",
|
|
96
|
+
Reload = "reload",
|
|
97
|
+
Replace = "replace",
|
|
98
|
+
Back = "back",
|
|
99
|
+
Forward = "forward"
|
|
100
|
+
}
|
|
101
|
+
export type NavigationError = CancelNavigation | RedirectNavigation;
|
|
102
|
+
export interface CancelNavigation {
|
|
103
|
+
readonly _tag: 'CancelNavigation';
|
|
104
|
+
}
|
|
105
|
+
export declare const cancelNavigation: Effect.Effect<never, CancelNavigation, never>;
|
|
106
|
+
export declare function isCancelNavigation(error: NavigationError): error is CancelNavigation;
|
|
107
|
+
export interface RedirectNavigation extends NavigateOptions {
|
|
108
|
+
readonly _tag: 'RedirectNavigation';
|
|
109
|
+
readonly url: string;
|
|
110
|
+
}
|
|
111
|
+
export declare const redirect: (url: string, options?: NavigateOptions) => Effect.Effect<never, RedirectNavigation, never>;
|
|
112
|
+
export declare function isRedirectNavigation(error: NavigationError): error is RedirectNavigation;
|
|
113
|
+
export interface OnNavigationOptions {
|
|
114
|
+
readonly passive?: boolean;
|
|
115
|
+
}
|
|
116
|
+
export declare const getCurrentUrl: Effect.Effect<Navigation, Cause.NoSuchElementException, URL>;
|
|
117
|
+
//# sourceMappingURL=Navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Navigation.d.ts","sourceRoot":"","sources":["../src/Navigation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as Brand from '@effect/data/Brand';
|
|
2
|
+
import * as Effect from '@effect/io/Effect';
|
|
3
|
+
import * as Context from '@typed/context';
|
|
4
|
+
export const Navigation = Context.Tag('Navigation');
|
|
5
|
+
export const navigate = (url, options) => Navigation.withEffect((n) => n.navigate(url, options));
|
|
6
|
+
export const onNavigation = (handler) => Navigation.withEffect((n) => n.onNavigation(handler));
|
|
7
|
+
export const canGoBack = Object.assign(Navigation.withEffect((n) => n.canGoBack), Navigation.withFx((n) => n.canGoBack));
|
|
8
|
+
export const back = Navigation.withEffect((n) => n.back);
|
|
9
|
+
export const canGoForward = Object.assign(Navigation.withEffect((n) => n.canGoForward), Navigation.withFx((n) => n.canGoForward));
|
|
10
|
+
export const forward = Navigation.withEffect((n) => n.forward);
|
|
11
|
+
export const reload = Navigation.withEffect((n) => n.reload);
|
|
12
|
+
export function NavigationEvent(destination, hashChange, navigationType) {
|
|
13
|
+
return { destination, hashChange, navigationType };
|
|
14
|
+
}
|
|
15
|
+
export const DestinationKey = Brand.nominal();
|
|
16
|
+
export function Destination(key, url, state) {
|
|
17
|
+
return { key, url, state };
|
|
18
|
+
}
|
|
19
|
+
export var NavigationType;
|
|
20
|
+
(function (NavigationType) {
|
|
21
|
+
NavigationType["Push"] = "push";
|
|
22
|
+
NavigationType["Reload"] = "reload";
|
|
23
|
+
NavigationType["Replace"] = "replace";
|
|
24
|
+
NavigationType["Back"] = "back";
|
|
25
|
+
NavigationType["Forward"] = "forward";
|
|
26
|
+
})(NavigationType || (NavigationType = {}));
|
|
27
|
+
export const cancelNavigation = Effect.fail({ _tag: 'CancelNavigation' });
|
|
28
|
+
export function isCancelNavigation(error) {
|
|
29
|
+
return error._tag === 'CancelNavigation';
|
|
30
|
+
}
|
|
31
|
+
export const redirect = (url, options = {}) => Effect.fail({ _tag: 'RedirectNavigation', url, ...options });
|
|
32
|
+
export function isRedirectNavigation(error) {
|
|
33
|
+
return error._tag === 'RedirectNavigation';
|
|
34
|
+
}
|
|
35
|
+
export const getCurrentUrl = Navigation.withEffect((n) => n.currentEntry.map((d) => d.url));
|
|
36
|
+
//# sourceMappingURL=Navigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Navigation.js","sourceRoot":"","sources":["../src/Navigation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Window, GlobalThis } from '@typed/dom';
|
|
2
|
+
import * as happyDom from 'happy-dom';
|
|
3
|
+
export interface ServerWindowOptions {
|
|
4
|
+
readonly url: string;
|
|
5
|
+
readonly innerWidth?: number;
|
|
6
|
+
readonly innerHeight?: number;
|
|
7
|
+
readonly settings?: {
|
|
8
|
+
readonly disableJavaScriptEvaluation: boolean;
|
|
9
|
+
readonly disableJavaScriptFileLoading: boolean;
|
|
10
|
+
readonly disableCSSFileLoading: boolean;
|
|
11
|
+
readonly enableFileSystemHttpRequests: boolean;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare function makeServerWindow(options?: ServerWindowOptions): Window & GlobalThis & Pick<InstanceType<typeof happyDom.Window>, 'happyDOM'>;
|
|
15
|
+
export declare const html5Doctype = "<!DOCTYPE html>";
|
|
16
|
+
//# sourceMappingURL=_makeServerWindow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_makeServerWindow.d.ts","sourceRoot":"","sources":["../src/_makeServerWindow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,KAAK,QAAQ,MAAM,WAAW,CAAA;AAErC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IAEpB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAClB,QAAQ,CAAC,2BAA2B,EAAE,OAAO,CAAA;QAC7C,QAAQ,CAAC,4BAA4B,EAAE,OAAO,CAAA;QAC9C,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAA;QACvC,QAAQ,CAAC,4BAA4B,EAAE,OAAO,CAAA;KAC/C,CAAA;CACF;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAO9E;AAED,eAAO,MAAM,YAAY,oBAAoB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_makeServerWindow.js","sourceRoot":"","sources":["../src/_makeServerWindow.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,WAAW,CAAA;AAerC,MAAM,UAAU,gBAAgB,CAC9B,OAA6B;IAE7B,MAAM,GAAG,GACP,IAAI,QAAQ,CAAC,MAAM,CAAC;QAClB,GAAG,OAAO;KACX,CAAQ,CAAA;IAEX,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as Layer from '@effect/io/Layer';
|
|
2
|
+
import { Location, History, Window, Storage, Document } from '@typed/dom';
|
|
3
|
+
import { DestinationKey, Navigation } from './Navigation.js';
|
|
4
|
+
export type NavigationServices = Window | Document | Location | History | Storage;
|
|
5
|
+
export interface DomNavigationOptions {
|
|
6
|
+
readonly initialKey?: DestinationKey;
|
|
7
|
+
readonly maxEntries?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare const dom: (options?: DomNavigationOptions) => Layer.Layer<NavigationServices, never, Navigation>;
|
|
10
|
+
export declare function getBasePathFromHref(href: string): string;
|
|
11
|
+
export declare function getCurrentPathFromLocation(location: Location | HTMLAnchorElement | URL): string;
|
|
12
|
+
//# sourceMappingURL=DOM.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DOM.d.ts","sourceRoot":"","sources":["../../src/DOM.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA;AAEzC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAqB,QAAQ,EAAE,MAAM,YAAY,CAAA;AAG5F,OAAO,EAAe,cAAc,EAAE,UAAU,EAAmB,MAAM,iBAAiB,CAAA;AAO1F,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAA;AAEjF,MAAM,WAAW,oBAAoB;IAGnC,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,CAAA;IAIpC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,eAAO,MAAM,GAAG,aACL,oBAAoB,KAC5B,WAAW,CAAC,kBAAkB,EAAE,KAAK,EAAE,UAAU,CAwHnD,CAAA;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,UAQ/C;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,QAAQ,GAAG,iBAAiB,GAAG,GAAG,UAEtF"}
|
package/dist/cjs/DOM.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.getCurrentPathFromLocation = exports.getBasePathFromHref = exports.dom = void 0;
|
|
27
|
+
const Function_1 = require("@effect/data/Function");
|
|
28
|
+
const Option = __importStar(require("@effect/data/Option"));
|
|
29
|
+
const Effect = __importStar(require("@effect/io/Effect"));
|
|
30
|
+
const Context = __importStar(require("@typed/context"));
|
|
31
|
+
const dom_1 = require("@typed/dom");
|
|
32
|
+
const Fx = __importStar(require("@typed/fx"));
|
|
33
|
+
const Navigation_js_1 = require("./Navigation.js");
|
|
34
|
+
const dom_intent_js_1 = require("./dom-intent.js");
|
|
35
|
+
const history_js_1 = require("./history.js");
|
|
36
|
+
const model_js_1 = require("./model.js");
|
|
37
|
+
const storage_js_1 = require("./storage.js");
|
|
38
|
+
const dom = (options = {}) => {
|
|
39
|
+
return Navigation_js_1.Navigation.layerScoped(Effect.gen(function* ($) {
|
|
40
|
+
// Get resources
|
|
41
|
+
const context = yield* $(Effect.context());
|
|
42
|
+
const history = Context.get(context, dom_1.History);
|
|
43
|
+
const document = Context.get(context, dom_1.Document);
|
|
44
|
+
const base = document.querySelector('base');
|
|
45
|
+
const baseHref = base ? getBasePathFromHref(base.href) : '/';
|
|
46
|
+
// Create model and intent
|
|
47
|
+
const [initialEntries, initialIndex] = yield* $((0, storage_js_1.getInitialValues)(baseHref, options));
|
|
48
|
+
const model = yield* $((0, model_js_1.makeModel)(initialEntries, initialIndex));
|
|
49
|
+
const intent = (0, dom_intent_js_1.makeIntent)(model, baseHref, options);
|
|
50
|
+
// Used to ensure ordering of navigation events
|
|
51
|
+
const lock = Effect.unsafeMakeSemaphore(1).withPermits(1);
|
|
52
|
+
const handleNavigationError = (depth) => (error) => Effect.provideContext(Effect.gen(function* ($) {
|
|
53
|
+
if (depth >= 50) {
|
|
54
|
+
throw new Error('Too many redirects. You may have an infinite loop of onNavigation handlers that are redirecting.');
|
|
55
|
+
}
|
|
56
|
+
switch (error._tag) {
|
|
57
|
+
case 'NoSuchElementException':
|
|
58
|
+
case 'CancelNavigation':
|
|
59
|
+
return yield* $(model.currentEntry.get);
|
|
60
|
+
case 'RedirectNavigation':
|
|
61
|
+
return yield* $(Effect.catchAll(intent.navigate(error.url, error), handleNavigationError(depth + 1)));
|
|
62
|
+
}
|
|
63
|
+
}), context);
|
|
64
|
+
const catchNavigationError = (effect) => Effect.catchAll(effect, handleNavigationError(0));
|
|
65
|
+
// Used to provide a locked effect with the current context
|
|
66
|
+
const provideLocked = (effect) => Effect.provideContext(lock(effect), context);
|
|
67
|
+
// Constructor our service
|
|
68
|
+
const navigation = {
|
|
69
|
+
back: provideLocked(catchNavigationError(intent.back(false))),
|
|
70
|
+
base: baseHref,
|
|
71
|
+
canGoBack: model.canGoBack,
|
|
72
|
+
canGoForward: model.canGoForward,
|
|
73
|
+
currentEntry: model.currentEntry,
|
|
74
|
+
entries: model.entries,
|
|
75
|
+
forward: provideLocked(catchNavigationError(intent.forward(false))),
|
|
76
|
+
goTo: (a) => (0, Function_1.pipe)(a, intent.goTo, Effect.catchAll((a) => (0, Function_1.pipe)(a, handleNavigationError(0), Effect.map(Option.some))), provideLocked),
|
|
77
|
+
navigate: (url, options) => (0, Function_1.pipe)(intent.navigate(url, options), catchNavigationError, provideLocked),
|
|
78
|
+
onNavigation: (handler, options) => (0, Function_1.pipe)(intent.onNavigation(handler, options), catchNavigationError, Effect.asUnit),
|
|
79
|
+
onNavigationEnd: (handler, options) => Effect.asUnit(intent.onNavigationEnd(handler, options)),
|
|
80
|
+
reload: provideLocked(catchNavigationError(intent.reload)),
|
|
81
|
+
};
|
|
82
|
+
// Patch History API to enable sending events
|
|
83
|
+
const historyEvents = yield* $(history_js_1.patchHistory);
|
|
84
|
+
// Listen to various events and update our model
|
|
85
|
+
yield* $(Fx.mergeAll(
|
|
86
|
+
// Listen to history events and keep track of entries
|
|
87
|
+
(0, Function_1.pipe)(historyEvents, Fx.flatMapEffect((event) => lock((0, history_js_1.onHistoryEvent)(event, intent)))),
|
|
88
|
+
// Listen to hash changes and push them to the history
|
|
89
|
+
(0, Function_1.pipe)((0, dom_1.addWindowListener)('hashchange', { capture: true }), Fx.flatMapEffect((ev) => lock(intent.push(ev.newURL, { state: history.state }, true)))),
|
|
90
|
+
// Listen to popstate events and go to the correct entry
|
|
91
|
+
(0, Function_1.pipe)((0, dom_1.addWindowListener)('popstate'), Fx.map((ev) => {
|
|
92
|
+
// TODO: Should we throw some kind of error here?
|
|
93
|
+
// This should never happen if you are solely using the Navigation Service
|
|
94
|
+
if (!ev.state || !ev.state.event) {
|
|
95
|
+
return Option.none();
|
|
96
|
+
}
|
|
97
|
+
const navigation = ev.state.event;
|
|
98
|
+
return Option.some(lock(intent.goTo(navigation.destination.key)));
|
|
99
|
+
}), Fx.compact, Fx.flattenEffect)), Fx.drain, Effect.forkScoped);
|
|
100
|
+
return navigation;
|
|
101
|
+
}));
|
|
102
|
+
};
|
|
103
|
+
exports.dom = dom;
|
|
104
|
+
function getBasePathFromHref(href) {
|
|
105
|
+
try {
|
|
106
|
+
const url = new URL(href);
|
|
107
|
+
return getCurrentPathFromLocation(url);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return href;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.getBasePathFromHref = getBasePathFromHref;
|
|
114
|
+
function getCurrentPathFromLocation(location) {
|
|
115
|
+
return location.pathname + location.search + location.hash;
|
|
116
|
+
}
|
|
117
|
+
exports.getCurrentPathFromLocation = getCurrentPathFromLocation;
|
|
118
|
+
//# sourceMappingURL=DOM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DOM.js","sourceRoot":"","sources":["../../src/DOM.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as Layer from '@effect/io/Layer';
|
|
2
|
+
import type { DomNavigationOptions } from './DOM.js';
|
|
3
|
+
import { Navigation } from './Navigation.js';
|
|
4
|
+
export interface MemoryNavigationOptions extends DomNavigationOptions {
|
|
5
|
+
readonly initialUrl: URL;
|
|
6
|
+
readonly initialState?: unknown;
|
|
7
|
+
readonly base?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function memory(options: MemoryNavigationOptions): Layer.Layer<never, never, Navigation>;
|
|
10
|
+
//# sourceMappingURL=Memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Memory.d.ts","sourceRoot":"","sources":["../../src/Memory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA;AAEzC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AACpD,OAAO,EAEL,UAAU,EAIX,MAAM,iBAAiB,CAAA;AAKxB,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACnE,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAA;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,uBAAuB,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CA6E9F"}
|