startupjs 0.61.10 → 0.61.12

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 (3) hide show
  1. package/app.js +75 -0
  2. package/package.json +7 -3
  3. package/test/app.test.js +99 -0
package/app.js ADDED
@@ -0,0 +1,75 @@
1
+ /**
2
+ * COMPAT-ONLY legacy entrypoint for old LMS code which still imports helpers from
3
+ * `startupjs/app`.
4
+ *
5
+ * Purpose:
6
+ * - preserve the old import surface while the app is being migrated to the newer
7
+ * router/runtime APIs
8
+ * - reduce mechanical diffs against older codebases which historically depended on
9
+ * `startupjs/app`
10
+ *
11
+ * Contract in this compat file:
12
+ * - `pathFor(name, params)` delegates to an application-registered implementation
13
+ * - `useHistory()` exposes the old imperative navigation shape on top of an
14
+ * application-registered `useRouter` implementation
15
+ *
16
+ * Explicit limitations:
17
+ * - this file is internal compat support and is intentionally not part of the
18
+ * main documented Startupjs API surface
19
+ * - it does NOT try to reintroduce the full historic `startupjs/app` package
20
+ * - only the exports needed by the LMS migration are provided here
21
+ * - `pathFor` must be initialized by the host app via `__setCompatPathFor()`
22
+ * - `useHistory` must be initialized by the host app via `__setCompatUseRouter()`
23
+ * - server-side `@startupjs/app/server` and the old default `App` export are out of
24
+ * scope for this package and must be handled separately if needed
25
+ */
26
+
27
+ let compatPathFor
28
+ let compatUseRouter
29
+
30
+ export function __setCompatPathFor (fn) {
31
+ if (typeof fn !== 'function') {
32
+ throw new Error('[startupjs/app] __setCompatPathFor expects a function')
33
+ }
34
+ compatPathFor = fn
35
+ }
36
+
37
+ export function __setCompatUseRouter (fn) {
38
+ if (typeof fn !== 'function') {
39
+ throw new Error('[startupjs/app] __setCompatUseRouter expects a function')
40
+ }
41
+ compatUseRouter = fn
42
+ }
43
+
44
+ export function __resetCompatPathForForTests () {
45
+ compatPathFor = undefined
46
+ compatUseRouter = undefined
47
+ }
48
+
49
+ export function pathFor (...args) {
50
+ if (typeof compatPathFor !== 'function') {
51
+ throw new Error(
52
+ '[startupjs/app] pathFor is not initialized. ' +
53
+ 'The host app must register a compat implementation via __setCompatPathFor().'
54
+ )
55
+ }
56
+ return compatPathFor(...args)
57
+ }
58
+
59
+ export function useHistory () {
60
+ if (typeof compatUseRouter !== 'function') {
61
+ throw new Error(
62
+ '[startupjs/app] useHistory is not initialized. ' +
63
+ 'The host app must register a compat useRouter implementation via __setCompatUseRouter().'
64
+ )
65
+ }
66
+ const router = compatUseRouter()
67
+ return {
68
+ push: (url, ...args) => router.navigate(url, ...args),
69
+ replace: (url, ...args) => router.replace(url, ...args),
70
+ goBack: (...args) => {
71
+ if (typeof router.back === 'function') return router.back(...args)
72
+ return router.navigate('..')
73
+ }
74
+ }
75
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "startupjs",
3
3
  "type": "module",
4
- "version": "0.61.10",
4
+ "version": "0.61.12",
5
5
  "engines": {
6
6
  "node": ">= 14"
7
7
  },
@@ -9,6 +9,7 @@
9
9
  "main": "index.js",
10
10
  "exports": {
11
11
  ".": "./index.js",
12
+ "./app": "./app.js",
12
13
  "./auth": "./auth.js",
13
14
  "./server": "./server.js",
14
15
  "./schema": "./schema.js",
@@ -31,7 +32,7 @@
31
32
  "dependencies": {
32
33
  "@startupjs/auth": "^0.61.2",
33
34
  "@startupjs/bundler": "^0.61.7",
34
- "@startupjs/cli": "^0.61.10",
35
+ "@startupjs/cli": "^0.61.11",
35
36
  "@startupjs/hooks": "^0.61.0",
36
37
  "@startupjs/isomorphic-helpers": "^0.61.0",
37
38
  "@startupjs/registry": "^0.61.0",
@@ -55,5 +56,8 @@
55
56
  "optional": true
56
57
  }
57
58
  },
58
- "gitHead": "7d2fe3104f2ebbc6934e269513c40b91c2616b05"
59
+ "scripts": {
60
+ "test": "node --experimental-specifier-resolution=node --test"
61
+ },
62
+ "gitHead": "39c6a5418b6752b31752981900257b4d84edd68f"
59
63
  }
@@ -0,0 +1,99 @@
1
+ import React from 'react'
2
+ import { renderToStaticMarkup } from 'react-dom/server'
3
+ import RouterContext from '@startupjs/utils/RouterContext'
4
+ import assert from 'node:assert/strict'
5
+ import test from 'node:test'
6
+ import {
7
+ __setCompatPathFor,
8
+ __setCompatUseRouter,
9
+ __resetCompatPathForForTests,
10
+ pathFor,
11
+ useHistory
12
+ } from '../app.js'
13
+
14
+ test.afterEach(() => {
15
+ __resetCompatPathForForTests()
16
+ })
17
+
18
+ test('pathFor throws a clear error until compat implementation is registered', () => {
19
+ assert.throws(
20
+ () => pathFor('admin:users'),
21
+ /pathFor is not initialized/
22
+ )
23
+ })
24
+
25
+ test('pathFor delegates to registered compat implementation', () => {
26
+ __setCompatPathFor((name, params = {}) => `/route/${name}/${params.id || ''}`)
27
+ assert.equal(pathFor('admin:tenant', { id: '42' }), '/route/admin:tenant/42')
28
+ })
29
+
30
+ test('useHistory maps push/replace/goBack to the router contract', () => {
31
+ const calls = []
32
+ const router = {
33
+ navigate: (...args) => calls.push(['navigate', ...args]),
34
+ replace: (...args) => calls.push(['replace', ...args]),
35
+ back: (...args) => calls.push(['back', ...args])
36
+ }
37
+ __setCompatUseRouter(() => router)
38
+
39
+ function Probe () {
40
+ const history = useHistory()
41
+ history.push('/one', { a: 1 })
42
+ history.replace('/two')
43
+ history.goBack()
44
+ return React.createElement('div')
45
+ }
46
+
47
+ renderToStaticMarkup(
48
+ React.createElement(
49
+ RouterContext.Provider,
50
+ { value: router },
51
+ React.createElement(Probe)
52
+ )
53
+ )
54
+
55
+ assert.deepEqual(calls, [
56
+ ['navigate', '/one', { a: 1 }],
57
+ ['replace', '/two'],
58
+ ['back']
59
+ ])
60
+ })
61
+
62
+ test('useHistory falls back to navigate("..") when router.back is missing', () => {
63
+ const calls = []
64
+ const router = {
65
+ navigate: (...args) => calls.push(['navigate', ...args]),
66
+ replace: (...args) => calls.push(['replace', ...args])
67
+ }
68
+ __setCompatUseRouter(() => router)
69
+
70
+ function Probe () {
71
+ const history = useHistory()
72
+ history.goBack()
73
+ return React.createElement('div')
74
+ }
75
+
76
+ renderToStaticMarkup(
77
+ React.createElement(
78
+ RouterContext.Provider,
79
+ { value: router },
80
+ React.createElement(Probe)
81
+ )
82
+ )
83
+
84
+ assert.deepEqual(calls, [
85
+ ['navigate', '..']
86
+ ])
87
+ })
88
+
89
+ test('useHistory throws a clear error until compat useRouter is registered', () => {
90
+ function Probe () {
91
+ useHistory()
92
+ return React.createElement('div')
93
+ }
94
+
95
+ assert.throws(
96
+ () => renderToStaticMarkup(React.createElement(Probe)),
97
+ /useHistory is not initialized/
98
+ )
99
+ })