@owlmeans/client 0.1.18-rc.2 → 0.1.18-rc.21

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 (66) hide show
  1. package/README.md +36 -12
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/client/SKILL.md +194 -19
  4. package/build/context.d.ts.map +1 -1
  5. package/build/context.js +1 -3
  6. package/build/context.js.map +1 -1
  7. package/build/entrypoint.d.ts +3 -0
  8. package/build/entrypoint.d.ts.map +1 -0
  9. package/build/entrypoint.js +4 -0
  10. package/build/entrypoint.js.map +1 -0
  11. package/build/helper.js +3 -3
  12. package/build/helper.js.map +1 -1
  13. package/build/index.d.ts +1 -1
  14. package/build/index.d.ts.map +1 -1
  15. package/build/index.js +1 -1
  16. package/build/index.js.map +1 -1
  17. package/build/navigate.d.ts.map +1 -1
  18. package/build/navigate.js +15 -18
  19. package/build/navigate.js.map +1 -1
  20. package/build/router.d.ts.map +1 -1
  21. package/build/router.js +12 -6
  22. package/build/router.js.map +1 -1
  23. package/build/services/debug.js.map +1 -1
  24. package/build/store.d.ts +19 -3
  25. package/build/store.d.ts.map +1 -1
  26. package/build/store.js +57 -50
  27. package/build/store.js.map +1 -1
  28. package/build/types.d.ts +16 -5
  29. package/build/types.d.ts.map +1 -1
  30. package/build/utils/entrypoint.d.ts +3 -0
  31. package/build/utils/entrypoint.d.ts.map +1 -0
  32. package/build/utils/{module.js → entrypoint.js} +2 -2
  33. package/build/utils/entrypoint.js.map +1 -0
  34. package/build/utils/index.d.ts +1 -1
  35. package/build/utils/index.d.ts.map +1 -1
  36. package/build/utils/index.js +1 -1
  37. package/build/utils/index.js.map +1 -1
  38. package/build/utils/route.d.ts.map +1 -1
  39. package/build/utils/route.js +12 -6
  40. package/build/utils/route.js.map +1 -1
  41. package/build/utils/router.d.ts +4 -4
  42. package/build/utils/router.d.ts.map +1 -1
  43. package/build/utils/router.js +8 -8
  44. package/build/utils/router.js.map +1 -1
  45. package/package.json +12 -12
  46. package/src/context.ts +1 -4
  47. package/src/entrypoint.ts +6 -0
  48. package/src/helper.tsx +6 -6
  49. package/src/index.ts +1 -1
  50. package/src/navigate.ts +16 -19
  51. package/src/router.ts +14 -10
  52. package/src/services/debug.ts +2 -2
  53. package/src/store.ts +71 -54
  54. package/src/types.ts +18 -5
  55. package/src/utils/{module.ts → entrypoint.ts} +2 -2
  56. package/src/utils/index.ts +1 -1
  57. package/src/utils/route.tsx +15 -8
  58. package/src/utils/router.ts +11 -11
  59. package/build/module.d.ts +0 -3
  60. package/build/module.d.ts.map +0 -1
  61. package/build/module.js +0 -4
  62. package/build/module.js.map +0 -1
  63. package/build/utils/module.d.ts +0 -3
  64. package/build/utils/module.d.ts.map +0 -1
  65. package/build/utils/module.js.map +0 -1
  66. package/src/module.ts +0 -6
package/src/navigate.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { useMemo } from 'react'
2
2
  import type { Navigator } from './types.js'
3
- import { EntrypointOutcome } from '@owlmeans/entrypoint'
4
3
  import { useContext } from './context.js'
5
4
  import type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
6
5
 
@@ -12,28 +11,26 @@ export const useNavigate = (): Navigator => {
12
11
  const navigator: Navigator = {
13
12
  _navigate: navigate,
14
13
 
15
- navigate: async (module, request) => {
16
- const [url, ok] = await module.call(request)
17
-
18
- if (ok === EntrypointOutcome.Ok) {
19
- if (url.startsWith('http')) {
20
- globalThis.location.href = url
21
- } else {
22
- navigate(url, {
23
- state: {
24
- ...module.route.route, silent: request?.silent
25
- },
26
- replace: request?.replace ?? false
27
- })
28
- }
14
+ navigate: async (entrypoint, request) => {
15
+ const url = await entrypoint.url(request)
16
+
17
+ if (url.startsWith('http')) {
18
+ globalThis.location.href = url
19
+ } else {
20
+ navigate(url, {
21
+ state: {
22
+ ...entrypoint.route.route, silent: request?.silent
23
+ },
24
+ replace: request?.replace ?? false
25
+ })
29
26
  }
30
27
  },
31
28
 
32
- go: async (alias, request) =>
33
- navigator.navigate(context.entrypoint<ClientEntrypoint<string>>(alias), request),
29
+ go: async (target, request) =>
30
+ navigator.navigate(context.entrypoint<ClientEntrypoint<string>>(target), request),
34
31
 
35
- press: (alias, request) => () => {
36
- void navigator.go(alias, request)
32
+ press: (target, request) => () => {
33
+ void navigator.go(target, request)
37
34
  },
38
35
 
39
36
  back: async () => {
package/src/router.ts CHANGED
@@ -1,18 +1,25 @@
1
1
  import type { FC } from 'react'
2
2
  import type { RouterModel, RouterProps, RouterProvider } from './types.js'
3
3
  import { createElement, useEffect, useRef, useState } from 'react'
4
- import { buildModuleTree, initializeRouter, visitModuleTree } from './utils/router.js'
4
+ import { buildEntrypointTree, initializeRouter, visitEntrypointTree } from './utils/router.js'
5
5
  import { createRouteRenderer } from './utils/route.js'
6
6
  import { useContext } from './context.js'
7
7
  import type { ClientConfig } from '@owlmeans/client-context'
8
8
  import type { ClientContext } from './types.js'
9
9
  import { assertContext } from '@owlmeans/context'
10
- import type { BasicConfig, BasicContext } from '@owlmeans/context'
11
10
  import type { LibraryRouter, RouteObject } from '@owlmeans/router'
12
11
 
13
12
  type Config = ClientConfig
14
13
  interface Context<C extends Config = Config> extends ClientContext<C> { }
15
14
 
15
+ /** A child path that keeps its leading separator reads as absolute, and the router rejects it. */
16
+ const relative = (segment: string): string => {
17
+ segment = segment.trim()
18
+ segment = segment.endsWith('/') ? segment.slice(0, -1) : segment
19
+
20
+ return segment.startsWith('/') ? segment.substring(1) : segment
21
+ }
22
+
16
23
  export const Router: FC<RouterProps> = ({ provide }) => {
17
24
  const progress = useRef(false)
18
25
  const context = useContext()
@@ -55,21 +62,18 @@ export const makeRouterModel = (): RouterModel => {
55
62
  routes: [],
56
63
  resolve: async (ctx) => {
57
64
  const context = assertContext<Config, Context>(ctx as Context, location)
58
- const moduleTree = buildModuleTree(context as Context)
59
-
60
- const reactRoutes: RouteObject[] = await visitModuleTree(moduleTree, async (module, children) => {
61
- const ctx = assertContext<BasicConfig, BasicContext<BasicConfig>>(
62
- (module.ctx ?? context) as BasicContext<BasicConfig>, location
63
- )
64
- await module.route.resolve(ctx)
65
+ const entrypointTree = buildEntrypointTree(context as Context)
65
66
 
67
+ const reactRoutes: RouteObject[] = await visitEntrypointTree(entrypointTree, async (module, children) => {
66
68
  const renderer = module.handle != null
67
69
  ? { Component: createRouteRenderer({ context, module, hasChildren: children.length > 0 }) }
68
70
  : undefined
69
71
 
72
+ // The React tree nests, so each node contributes only its OWN segment — its ancestors are
73
+ // the branches it hangs under and already carry theirs.
70
74
  const route: RouteObject = {
71
75
  ...(module.route.route.default ? { index: true } as any : undefined),
72
- ...(!module.route.route.default ? { path: module.getPath(true), children } : undefined),
76
+ ...(!module.route.route.default ? { path: relative(module.segment()), children } : undefined),
73
77
  ...renderer
74
78
  }
75
79
 
@@ -62,13 +62,13 @@ export const createDebugService = (alias: string = DEF_DEBUG_ALIAS): DebugServic
62
62
  }, service => async () => {
63
63
  service.initialized = true
64
64
  const context = assertContext(service.ctx, location) as ClientContext
65
- const record = await context.getConfigResource().load<DebugConfigRecord>(DEBUG_CONFIG_KEY)
65
+ const record = await context.getConfigResource<DebugConfigRecord>().load(DEBUG_CONFIG_KEY)
66
66
  if (record?.states != null) {
67
67
  service.addItem({
68
68
  alias: 'reset-states',
69
69
  title: `Reset states`,
70
70
  action: async (modal, context) => {
71
- const record = await context.getConfigResource().load<DebugConfigRecord>(DEBUG_CONFIG_KEY)
71
+ const record = await context.getConfigResource<DebugConfigRecord>().load(DEBUG_CONFIG_KEY)
72
72
  if (record?.states != null) {
73
73
  await service.erase(record.states)
74
74
  context.rerender()
package/src/store.ts CHANGED
@@ -1,68 +1,85 @@
1
- import { useEffect, useId, useMemo, useState } from 'react'
2
- import type { StateModel, UseStoreHelper, UseStoreHelperOptions, UseStoreListHelper } from '@owlmeans/state'
3
- import { useContext } from './context.js'
1
+ import { useMemo, useSyncExternalStore } from 'react'
4
2
  import type { ResourceRecord } from '@owlmeans/resource'
3
+ import type { StateModel } from '@owlmeans/state'
4
+ import { useContext } from './context.js'
5
+ import type { UseStoreListOptions } from './types.js'
5
6
 
6
- export const useStoreModel: UseStoreHelper = (id, opts) => {
7
- const list = useStoreList(id, opts)
7
+ /**
8
+ * Turn one state subscription into the pair `useSyncExternalStore` wants.
9
+ *
10
+ * The value is cached rather than rebuilt per render: the hook is asked for a snapshot on every
11
+ * render and must answer with the same reference until something actually changed, or React
12
+ * re-renders forever. A state subscription hands its value over synchronously, so the first
13
+ * snapshot is taken by subscribing and unsubscribing again — no render ever runs without one,
14
+ * and no subscription outlives the call.
15
+ */
16
+ const bind = <V>(subscribe: (listener: (value: V) => void) => () => void) => {
17
+ let current: V | undefined
18
+ let seeded = false
8
19
 
9
- if (list.length < 1) {
10
- throw new SyntaxError('Store always return model and create it if not exists')
20
+ const capture = (notify?: () => void) => (value: V) => {
21
+ current = value
22
+ seeded = true
23
+ notify?.()
11
24
  }
12
25
 
13
- return list[0]
14
- }
26
+ return {
27
+ subscribe: (notify: () => void) => subscribe(capture(notify)),
28
+ snapshot: (): V => {
29
+ if (!seeded) {
30
+ subscribe(capture())()
31
+ }
15
32
 
16
- export const useStoreList: UseStoreListHelper = (ids, opts) => {
17
- if (typeof ids === 'object' && !Array.isArray(ids)) {
18
- opts = ids
19
- }
20
- const params: UseStoreHelperOptions<ResourceRecord> = typeof opts === 'object' ? opts : {}
21
- if (typeof ids === 'string' || Array.isArray(ids)) {
22
- params.id = ids
23
- }
24
- if (typeof opts === 'string') {
25
- params.resource = opts
26
- } else if (typeof opts === 'boolean') {
27
- params.listen = opts
33
+ return current as V
34
+ }
28
35
  }
29
- params.listen = params.listen ?? true
36
+ }
30
37
 
38
+ /**
39
+ * One record from a state resource, live.
40
+ *
41
+ * It never throws for missing data: an id the store knows nothing about yields a model whose
42
+ * `empty` is true — reading `record` gives the resource's configured default, and nothing is
43
+ * written into the store on the way. An ABSENT id is the same answer rather than an error, since
44
+ * a screen renders before the record that supplies the id has arrived; on a `single` resource an
45
+ * absent id addresses its sole record. Writing through an empty model with no id is refused.
46
+ */
47
+ export const useStoreModel = <T extends ResourceRecord = ResourceRecord>(
48
+ id?: string, alias?: string
49
+ ): StateModel<T> => {
31
50
  const context = useContext()
32
- const resource = useMemo(() => context.getStateResource(params.resource), [params.resource])
51
+ const resource = useMemo(() => context.getStateResource<T>(alias), [context, alias])
52
+ const store = useMemo(
53
+ () => bind<StateModel<T>>(listener => resource.watch(id, listener)),
54
+ [resource, id]
55
+ )
33
56
 
34
- const deps = [
35
- Array.isArray(params.id) ? params.id.join(',') : params.id,
36
- params.query == null,
37
- JSON.stringify(params.default),
38
- params.listen
39
- ]
40
-
41
- const id = useId()
42
- const [models, setModels] = useState<StateModel<ResourceRecord>[]>([])
43
-
44
- let _return = [...models]
45
-
46
- const unsubscribe = useMemo(() => {
47
- const [unsubscribe, _initialModels] = resource.subscribe({
48
- _systemId: id,
49
- id: params.id,
50
- listener: models => {
51
- params.listen && setModels(models)
52
- },
53
- default: params.default,
54
- query: params.query,
55
- })
56
- setModels(_initialModels)
57
-
58
- if (_return.length < 1) {
59
- _return.push(..._initialModels)
60
- }
57
+ return useSyncExternalStore(store.subscribe, store.snapshot, store.snapshot)
58
+ }
61
59
 
62
- return unsubscribe
63
- }, deps)
60
+ /**
61
+ * A live LIST from a state resource: every record the query accepts, re-evaluated on every write
62
+ * that changes the answer, so a screen never recomputes ids and never re-subscribes to keep up.
63
+ * Omitting `query` matches everything.
64
+ */
65
+ export const useStoreList = <T extends ResourceRecord = ResourceRecord>(
66
+ opts?: UseStoreListOptions<T>
67
+ ): StateModel<T>[] => {
68
+ const context = useContext()
69
+ const resource = useMemo(() => context.getStateResource<T>(opts?.resource), [context, opts?.resource])
64
70
 
65
- useEffect(() => unsubscribe, deps)
71
+ /**
72
+ * The subscription is keyed on the query's CONTENT, not on whether one was given: a screen
73
+ * that narrows its filter has to re-subscribe, and keyed on identity it kept answering the
74
+ * first filter it ever saw with nothing to say the list had gone stale.
75
+ */
76
+ const key = JSON.stringify([opts?.query ?? null, opts?.sort ?? null])
77
+ const store = useMemo(
78
+ () => bind<StateModel<T>[]>(
79
+ listener => resource.query(opts?.query, listener, { sort: opts?.sort })
80
+ ),
81
+ [resource, key]
82
+ )
66
83
 
67
- return _return as StateModel<any>[]
84
+ return useSyncExternalStore(store.subscribe, store.snapshot, store.snapshot)
68
85
  }
package/src/types.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import type { PropsWithChildren, FC, DependencyList } from 'react'
2
2
  import type { AbstractRequest } from '@owlmeans/entrypoint'
3
3
  import type { ClientConfig, ClientContext as BasicClientContext } from '@owlmeans/client-context'
4
+ import type { Criteria, ResourceRecord, Sort } from '@owlmeans/resource'
4
5
  import type { StateResourceAppend } from '@owlmeans/state'
5
6
  import type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
6
7
  import type { DebugServiceAppend, ModalServiceAppend } from './components/types.js'
7
8
  import type { ConfigResourceAppend } from '@owlmeans/config'
8
- import type { ConfigRecord } from '@owlmeans/context'
9
+ import type { ConfigRecord, EntrypointReference } from '@owlmeans/context'
9
10
  import type { NavigateFunction, RouterService, Location, RouteObject, LibraryRouter } from '@owlmeans/router'
10
11
 
11
12
 
@@ -35,10 +36,10 @@ export interface AppProps extends PropsWithChildren {
35
36
  noRouter?: boolean
36
37
  }
37
38
 
38
- export interface RoutedComponent<ExtraProps = {}> extends FC<PropsWithChildren<ModuleContextParams & ExtraProps>> {
39
+ export interface RoutedComponent<ExtraProps = {}> extends FC<PropsWithChildren<EntrypointContextParams & ExtraProps>> {
39
40
  }
40
41
 
41
- export interface ModuleContextParams<T extends {} = {}> {
42
+ export interface EntrypointContextParams<T extends {} = {}> {
42
43
  alias: string
43
44
  params: AbstractRequest<T>['params']
44
45
  path: string
@@ -61,13 +62,16 @@ export interface NavRequest<T extends Record<string, any> = Record<string, any>>
61
62
  silent?: boolean
62
63
  }
63
64
 
65
+ /** A navigation target is a protocol reference in application code, with strings retained for adapters. */
66
+ export type EntrypointTarget = EntrypointReference | string
67
+
64
68
  export interface Navigator {
65
69
  _navigate: NavigateFunction
66
70
  navigate: <R extends NavRequest = NavRequest>(module: ClientEntrypoint<string, AbstractRequest>, request?: R) => Promise<void>
67
- go: <R extends NavRequest = NavRequest>(alias: string, request?: R) => Promise<void>
71
+ go: <R extends NavRequest = NavRequest>(target: EntrypointTarget, request?: R) => Promise<void>
68
72
  back: () => Promise<void>
69
73
  pressBack: () => () => void
70
- press: <R extends NavRequest = NavRequest>(alias: string, request?: R) => () => void
74
+ press: <R extends NavRequest = NavRequest>(target: EntrypointTarget, request?: R) => () => void
71
75
  location: <R extends NavRequest = NavRequest>() => Location<R>
72
76
  }
73
77
 
@@ -79,3 +83,12 @@ export interface UseValueParams<T> {
79
83
  default?: T
80
84
  deps?: DependencyList
81
85
  }
86
+
87
+ /** What `useStoreList` subscribes to. Every field is optional; nothing at all means everything. */
88
+ export interface UseStoreListOptions<T extends ResourceRecord = ResourceRecord> {
89
+ /** The live query. Omitted or `{}` matches every record the resource holds. */
90
+ query?: Criteria<T>
91
+ sort?: Sort<T>[]
92
+ /** Which state resource to read; the context's default one when omitted. */
93
+ resource?: string
94
+ }
@@ -1,12 +1,12 @@
1
1
 
2
2
  import { createContext } from 'react'
3
- import type { ModuleContextParams, ClientContext } from '../types.js'
3
+ import type { EntrypointContextParams, ClientContext } from '../types.js'
4
4
  import type { ClientConfig } from '@owlmeans/client-context'
5
5
 
6
6
  type Config = ClientConfig
7
7
  interface Context<C extends Config = Config> extends ClientContext<C> { }
8
8
 
9
- export const ModuleContext = createContext<ModuleContextParams>({
9
+ export const EntrypointContext = createContext<EntrypointContextParams>({
10
10
  alias: '',
11
11
  params: {},
12
12
  path: '',
@@ -1,4 +1,4 @@
1
1
 
2
2
  export * from './router.js'
3
3
  export * from './route.js'
4
- export * from './module.js'
4
+ export * from './entrypoint.js'
@@ -1,5 +1,5 @@
1
1
  import type { FC, PropsWithChildren, ReactElement } from 'react'
2
- import type { ModuleContextParams, RoutedComponent, ClientContext } from '../types.js'
2
+ import type { EntrypointContextParams, RoutedComponent, ClientContext } from '../types.js'
3
3
  import { isValidElement, memo, useEffect } from 'react'
4
4
  import type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
5
5
  import { provideRequest } from '@owlmeans/client-entrypoint'
@@ -15,10 +15,17 @@ export const createRouteRenderer: (params: RendererParams) => FC = ({ context, m
15
15
  const params = context.router().useParams()
16
16
  const reply = provideResponse()
17
17
 
18
+ // Own guards plus every ancestor's — the same set the request would be judged by. Whether a
19
+ // screen is guarded is a question about THIS list being non-empty, never about the declaration
20
+ // carrying a `guards` property: binding always assigns the array, empty when nothing was
21
+ // declared, and an empty list means an open screen. Asking the wrong question refuses every
22
+ // guest screen with `frontend-guard`, since no guard can match when there are none.
23
+ const aliases = module.getGuards()
24
+
18
25
  useEffect(() => {
19
- if (module.guards != null) {
20
- const guards = module.getGuards().map(guard => context.service<GuardService>(guard))
21
- const request = provideRequest(module.alias, module.getPath())
26
+ if (aliases.length > 0) {
27
+ const guards = aliases.map(guard => context.service<GuardService>(guard))
28
+ const request = provideRequest(module.alias, module.path())
22
29
  const reply = provideResponse()
23
30
  let canceled = false
24
31
  Promise.all(guards.map(async guard => {
@@ -38,10 +45,10 @@ export const createRouteRenderer: (params: RendererParams) => FC = ({ context, m
38
45
  })
39
46
  return () => { canceled = true }
40
47
  }
41
- }, module.guards ?? [])
48
+ }, aliases)
42
49
 
43
50
  let Renderer: HandledRenderer<{}> = module.handle?.({
44
- alias: module.alias, path: module.getPath(),
51
+ alias: module.alias, path: module.path(),
45
52
  params, body: {}, headers: {}, query: {},
46
53
  }, reply) as HandledRenderer<{}>
47
54
 
@@ -55,8 +62,8 @@ export const createRouteRenderer: (params: RendererParams) => FC = ({ context, m
55
62
  const Outlet = context.router().outlet()
56
63
  if (isComponent(Renderer)) {
57
64
  const EnsuredRenderer = memo(Renderer) as RoutedComponent
58
- const props: ModuleContextParams = {
59
- context, params, alias: module.getAlias(), path: module.getPath()
65
+ const props: EntrypointContextParams = {
66
+ context, params, alias: module.alias, path: module.path()
60
67
  }
61
68
  if (hasChildren) {
62
69
  return <EnsuredRenderer {...props}><Outlet /></EnsuredRenderer>
@@ -7,8 +7,8 @@ import type { ClientContext } from '../types.js'
7
7
  type Config = ClientConfig
8
8
  interface Context<C extends Config = Config> extends ClientContext<C> { }
9
9
 
10
- export const buildModuleTree = <R, C extends Config = Config, T extends Context<C> = Context<C>>(context: T): ModuleTree<R> => {
11
- const modules = context.entrypoints<ClientEntrypoint<R>>().filter(
10
+ export const buildEntrypointTree = <R, C extends Config = Config, T extends Context<C> = Context<C>>(context: T): EntrypointTree<R> => {
11
+ const entrypoints = context.entrypoints<ClientEntrypoint<R>>().filter(
12
12
  module => module.route.route.type === AppType.Frontend
13
13
  && (module.sticky || module.route.route.service == null
14
14
  || module.route.route.service === context.cfg.service)
@@ -17,8 +17,8 @@ export const buildModuleTree = <R, C extends Config = Config, T extends Context<
17
17
  const flatTree = new Map<ClientEntrypoint<R>, ClientEntrypoint<R>[]>()
18
18
  const roots: ClientEntrypoint<R>[] = []
19
19
 
20
- modules.forEach(module => {
21
- const parentAlias = module.getParentAlias()
20
+ entrypoints.forEach(module => {
21
+ const parentAlias = module.route.route.parent
22
22
  if (parentAlias == null) {
23
23
  roots.push(module)
24
24
  } else {
@@ -29,18 +29,18 @@ export const buildModuleTree = <R, C extends Config = Config, T extends Context<
29
29
  }
30
30
  })
31
31
 
32
- const reduceModules = (modules: ClientEntrypoint<R>[]): ModuleTree<R> => modules.reduce(
33
- (tree, module) => tree.set(module, reduceModules(flatTree.get(module) ?? [])), new Map()
32
+ const reduceEntrypoints = (entrypoints: ClientEntrypoint<R>[]): EntrypointTree<R> => entrypoints.reduce(
33
+ (tree, module) => tree.set(module, reduceEntrypoints(flatTree.get(module) ?? [])), new Map()
34
34
  )
35
35
 
36
- return reduceModules(roots)
36
+ return reduceEntrypoints(roots)
37
37
  }
38
38
 
39
- export const visitModuleTree = async <T, R>(tree: ModuleTree<T>, visitor: ModuleTreeVisitor<T, R>): Promise<R[]> =>
39
+ export const visitEntrypointTree = async <T, R>(tree: EntrypointTree<T>, visitor: EntrypointTreeVisitor<T, R>): Promise<R[]> =>
40
40
  Array.from(tree.entries()).reduce<Promise<R[]>>(
41
41
  async (result, [module, tree], _, source) => [
42
42
  ...(await result),
43
- await visitor(module, await visitModuleTree(tree, visitor), source.length === 1)
43
+ await visitor(module, await visitEntrypointTree(tree, visitor), source.length === 1)
44
44
  ], Promise.resolve([]))
45
45
 
46
46
  export const initializeRouter = async (context: Context) => {
@@ -52,9 +52,9 @@ export const initializeRouter = async (context: Context) => {
52
52
  return await model.resolve(context)
53
53
  }
54
54
 
55
- export interface ModuleTreeVisitor<T, R> {
55
+ export interface EntrypointTreeVisitor<T, R> {
56
56
  (module: ClientEntrypoint<T>, children: R[], alone: boolean): Promise<R>
57
57
  }
58
58
 
59
- interface ModuleTree<T> extends Map<ClientEntrypoint<T>, ModuleTree<T>> {
59
+ interface EntrypointTree<T> extends Map<ClientEntrypoint<T>, EntrypointTree<T>> {
60
60
  }
package/build/module.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import type { ModuleContextParams } from './types.js';
2
- export declare const useModule: <T extends {} = {}>() => ModuleContextParams<T>;
3
- //# sourceMappingURL=module.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAErD,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,EAAE,GAAG,EAAE,OAAoC,mBAAmB,CAAC,CAAC,CAAC,CAAA"}
package/build/module.js DELETED
@@ -1,4 +0,0 @@
1
- import { useContext } from 'react';
2
- import { ModuleContext } from './utils/index.js';
3
- export const useModule = () => useContext(ModuleContext);
4
- //# sourceMappingURL=module.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAGhD,MAAM,CAAC,MAAM,SAAS,GAAG,GAAsB,EAAE,CAAC,UAAU,CAAC,aAAa,CAA2B,CAAA"}
@@ -1,3 +0,0 @@
1
- import type { ModuleContextParams } from '../types.js';
2
- export declare const ModuleContext: import("react").Context<ModuleContextParams<{}>>;
3
- //# sourceMappingURL=module.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/utils/module.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,aAAa,CAAA;AAMrE,eAAO,MAAM,aAAa,kDAKxB,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/utils/module.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAOrC,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAsB;IAC9D,KAAK,EAAE,EAAE;IACT,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,EAAa;CACvB,CAAC,CAAA"}
package/src/module.ts DELETED
@@ -1,6 +0,0 @@
1
-
2
- import { useContext } from 'react'
3
- import { ModuleContext } from './utils/index.js'
4
- import type { ModuleContextParams } from './types.js'
5
-
6
- export const useModule = <T extends {} = {}>() => useContext(ModuleContext) as ModuleContextParams<T>