@webjsdev/core 0.7.31 → 0.7.32

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/index-browser.js CHANGED
@@ -28,7 +28,7 @@ export { WebComponent, prop } from './src/component.js';
28
28
  export { register, lookup, lookupModuleUrl, isLazy, allTags, primeModuleUrl, tagOf } from './src/registry.js';
29
29
  export { render } from './src/render-client.js';
30
30
  export { escapeText, escapeAttr } from './src/escape.js';
31
- export { notFound, redirect, isNotFound, isRedirect } from './src/nav.js';
31
+ export { notFound, redirect, forbidden, unauthorized, isNotFound, isRedirect, isForbidden, isUnauthorized } from './src/nav.js';
32
32
  export { cspNonce } from './src/csp-nonce.js';
33
33
  export { repeat, isRepeat } from './src/repeat.js';
34
34
  export { Suspense, isSuspense } from './src/suspense.js';
package/index.d.ts CHANGED
@@ -74,7 +74,7 @@ export { register, lookup, lookupModuleUrl, isLazy, allTags, primeModuleUrl, tag
74
74
  export { renderToString, renderToStream } from './src/render-server.js';
75
75
  export { render } from './src/render-client.js';
76
76
  export { escapeText, escapeAttr } from './src/escape.js';
77
- export { notFound, redirect, isNotFound, isRedirect } from './src/nav.js';
77
+ export { notFound, redirect, forbidden, unauthorized, isNotFound, isRedirect, isForbidden, isUnauthorized } from './src/nav.js';
78
78
  export { repeat, isRepeat } from './src/repeat.js';
79
79
  export { Suspense, isSuspense } from './src/suspense.js';
80
80
  export { connectWS } from './src/websocket-client.js';
package/index.js CHANGED
@@ -13,7 +13,7 @@ export { register, lookup, lookupModuleUrl, isLazy, allTags, primeModuleUrl, tag
13
13
  export { renderToString, renderToStream } from './src/render-server.js';
14
14
  export { render } from './src/render-client.js';
15
15
  export { escapeText, escapeAttr } from './src/escape.js';
16
- export { notFound, redirect, isNotFound, isRedirect } from './src/nav.js';
16
+ export { notFound, redirect, forbidden, unauthorized, isNotFound, isRedirect, isForbidden, isUnauthorized } from './src/nav.js';
17
17
  export { cspNonce, setCspNonceProvider } from './src/csp-nonce.js';
18
18
  export { repeat, isRepeat } from './src/repeat.js';
19
19
  export { Suspense, isSuspense } from './src/suspense.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webjsdev/core",
3
- "version": "0.7.31",
3
+ "version": "0.7.32",
4
4
  "type": "module",
5
5
  "description": "webjs core runtime - html/css tags, WebComponent base, isomorphic renderers",
6
6
  "types": "./index.d.ts",
package/src/nav.d.ts CHANGED
@@ -1,4 +1,8 @@
1
1
  export function notFound(): never;
2
2
  export function redirect(url: string, status?: number | { status?: number }): never;
3
+ export function forbidden(): never;
4
+ export function unauthorized(): never;
3
5
  export function isNotFound(e: unknown): boolean;
4
6
  export function isRedirect(e: unknown): boolean;
7
+ export function isForbidden(e: unknown): boolean;
8
+ export function isUnauthorized(e: unknown): boolean;
package/src/nav.js CHANGED
@@ -13,6 +13,8 @@
13
13
 
14
14
  const NOT_FOUND = Symbol.for('webjs.notFound');
15
15
  const REDIRECT = Symbol.for('webjs.redirect');
16
+ const FORBIDDEN = Symbol.for('webjs.forbidden');
17
+ const UNAUTHORIZED = Symbol.for('webjs.unauthorized');
16
18
 
17
19
  /** @returns {never} */
18
20
  export function notFound() {
@@ -21,6 +23,35 @@ export function notFound() {
21
23
  throw err;
22
24
  }
23
25
 
26
+ /**
27
+ * Throw a 403 Forbidden sentinel the SSR pipeline catches (#848, Next 15/16
28
+ * parity). Renders the nearest `forbidden.{js,ts}` boundary at status 403, or a
29
+ * default 403 page when none exists. Use for an authenticated user who lacks
30
+ * permission (contrast `unauthorized()` for a not-logged-in user).
31
+ *
32
+ * @returns {never}
33
+ */
34
+ export function forbidden() {
35
+ const err = new Error('webjs: forbidden()');
36
+ /** @type any */ (err).__webjs = FORBIDDEN;
37
+ throw err;
38
+ }
39
+
40
+ /**
41
+ * Throw a 401 Unauthorized sentinel the SSR pipeline catches (#848, Next 15/16
42
+ * parity). Renders the nearest `unauthorized.{js,ts}` boundary at status 401, or
43
+ * a default 401 page when none exists. Use for a request that is not
44
+ * authenticated (contrast `forbidden()` for an authenticated-but-not-allowed
45
+ * user).
46
+ *
47
+ * @returns {never}
48
+ */
49
+ export function unauthorized() {
50
+ const err = new Error('webjs: unauthorized()');
51
+ /** @type any */ (err).__webjs = UNAUTHORIZED;
52
+ throw err;
53
+ }
54
+
24
55
  /**
25
56
  * Throw a redirect sentinel the SSR pipeline catches and turns into a 3xx.
26
57
  *
@@ -62,3 +93,13 @@ export function isNotFound(e) {
62
93
  export function isRedirect(e) {
63
94
  return !!e && /** @type any */ (e).__webjs === REDIRECT;
64
95
  }
96
+
97
+ /** @param {unknown} e */
98
+ export function isForbidden(e) {
99
+ return !!e && /** @type any */ (e).__webjs === FORBIDDEN;
100
+ }
101
+
102
+ /** @param {unknown} e */
103
+ export function isUnauthorized(e) {
104
+ return !!e && /** @type any */ (e).__webjs === UNAUTHORIZED;
105
+ }
package/src/routes.d.ts CHANGED
@@ -84,6 +84,14 @@ export type RouteParams<R extends string> = R extends keyof RouteParamMap
84
84
  ? RouteParamMap[R]
85
85
  : Record<string, string>;
86
86
 
87
+ /**
88
+ * A value that is BOTH synchronously usable as `T` and `await`-able to `T`
89
+ * (#848). The webjs runtime hands `params` / `searchParams` as a plain object
90
+ * carrying a non-enumerable `then`, so `params.id` and `await params` both
91
+ * work; this type expresses that dual nature to TypeScript.
92
+ */
93
+ export type Awaitable<T> = T & PromiseLike<T>;
94
+
87
95
  /**
88
96
  * The argument a page default-export receives. Mirrors the `ctx` object
89
97
  * packages/server/src/ssr.js builds: `{ params, searchParams, url,
@@ -94,16 +102,22 @@ export type RouteParams<R extends string> = R extends keyof RouteParamMap
94
102
  * `Object.fromEntries(url.searchParams.entries())` (so a repeated key is
95
103
  * last-wins `string`, never an array). The wider type keeps a future
96
104
  * multi-value reader source-compatible.
105
+ *
106
+ * `params` / `searchParams` are `Awaitable<T>` (#848): synchronously readable
107
+ * (`params.id`) AND `await`-able (`const { id } = await params`) for Next
108
+ * 15/16 muscle-memory parity. The runtime object carries a non-enumerable
109
+ * `then` (see packages/server/src/thenable-params.js), so a spread / JSON /
110
+ * `Object.keys` sees only the data keys.
97
111
  */
98
112
  export interface PageProps<R extends string = string> {
99
113
  /**
100
114
  * Path params. A generated dynamic route narrows this to its exact shape
101
115
  * (`{ slug: string }`); a static or un-generated route is
102
- * `Record<string, string>`.
116
+ * `Record<string, string>`. Sync-readable and `await`-able (#848).
103
117
  */
104
- params: R extends keyof RouteParamMap ? RouteParamMap[R] : Record<string, string>;
105
- /** Query string, as an object. Repeated keys are last-wins at runtime. */
106
- searchParams: Record<string, string | string[]>;
118
+ params: Awaitable<R extends keyof RouteParamMap ? RouteParamMap[R] : Record<string, string>>;
119
+ /** Query string, as an object. Repeated keys are last-wins at runtime. Sync-readable and `await`-able (#848). */
120
+ searchParams: Awaitable<Record<string, string | string[]>>;
107
121
  /** The full request URL string. */
108
122
  url: string;
109
123
  /**
@@ -132,5 +146,6 @@ export interface LayoutProps<R extends string = string> extends PageProps<R> {
132
146
  * narrow them against a generated route the same way `PageProps` does.
133
147
  */
134
148
  export interface RouteHandlerContext<R extends string = string> {
135
- params: R extends keyof RouteParamMap ? RouteParamMap[R] : Record<string, string>;
149
+ /** Sync-readable and `await`-able (#848), same as `PageProps['params']`. */
150
+ params: Awaitable<R extends keyof RouteParamMap ? RouteParamMap[R] : Record<string, string>>;
136
151
  }