Skip to content

Commit 4bd6bdb

Browse files
committed
Add Async type variants for the various layout and page functions
1 parent 0c52f39 commit 4bd6bdb

File tree

13 files changed

+162
-53
lines changed

13 files changed

+162
-53
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ coverage
1010

1111
*.d.ts
1212
*.d.ts.map
13+
!types/**/*.d.ts
14+
!types/**/*.d.ts.map

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,13 +1183,18 @@ You can use `domstack`'s built-in types to strongly type your layout, page, and
11831183
```ts
11841184
import type {
11851185
LayoutFunction,
1186+
AsyncLayoutFunction,
11861187
PostVarsFunction,
1188+
AsyncPostVarsFunction,
11871189
PageFunction,
1190+
AsyncPageFunction,
11881191
TemplateFunction,
11891192
TemplateAsyncIterator
11901193
} from '@domstack/static'
11911194
```
11921195

1196+
> **Note:** All function types have both synchronous and asynchronous variants (e.g., `LayoutFunction` and `AsyncLayoutFunction`). Use the async variants when your function is an `async` function.
1197+
11931198
They are all generic and accept a variable template that you can develop and share between files.
11941199

11951200
#### Advanced Type Parameters for PageFunction and LayoutFunction

index.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/**
22
* @import { DomStackOpts as DomStackOpts, Results } from './lib/builder.js'
33
* @import { FSWatcher, Stats } from 'node:fs'
4-
* @import { PostVarsFunction, LayoutFunction } from './lib/build-pages/page-data.js'
5-
* @import { PageFunction } from './lib/build-pages/page-builders/page-writer.js'
4+
* @import { PostVarsFunction, AsyncPostVarsFunction, AsyncLayoutFunction, LayoutFunction } from './lib/build-pages/page-data.js'
5+
* @import { PageFunction, AsyncPageFunction } from './lib/build-pages/page-builders/page-writer.js'
66
* @import { TemplateFunction } from './lib/build-pages/page-builders/template-builder.js'
77
* @import { TemplateAsyncIterator } from './lib/build-pages/page-builders/template-builder.js'
88
* @import { TemplateOutputOverride } from './lib/build-pages/page-builders/template-builder.js'
@@ -36,19 +36,39 @@ import { DomStackAggregateError } from './lib/helpers/dom-stack-aggregate-error.
3636
* @typedef {LayoutFunction<Vars, PageReturn, LayoutReturn>} LayoutFunction
3737
*/
3838

39+
/**
40+
* @template {Record<string, any>} Vars - The type of variables passed to the async layout function
41+
* @template [PageReturn=any] PageReturn - The return type of the page function (defaults to any)
42+
* @template [LayoutReturn=string] LayoutReturn - The return type of the layout function (defaults to string)
43+
* @typedef {AsyncLayoutFunction<Vars, PageReturn, LayoutReturn>} AsyncLayoutFunction
44+
*/
45+
3946
/**
4047
* @template {Record<string, any>} Vars - The type of variables for the post vars function
4148
* @template [PageReturn=any] PageReturn - The return type of the page function (defaults to any)
4249
* @template [LayoutReturn=string] LayoutReturn - The return type of the layout function (defaults to string)
4350
* @typedef {PostVarsFunction<Vars, PageReturn, LayoutReturn>} PostVarsFunction
4451
*/
4552

53+
/**
54+
* @template {Record<string, any>} Vars - The type of variables for the async post vars function
55+
* @template [PageReturn=any] PageReturn - The return type of the page function (defaults to any)
56+
* @template [LayoutReturn=string] LayoutReturn - The return type of the layout function (defaults to string)
57+
* @typedef {AsyncPostVarsFunction<Vars, PageReturn, LayoutReturn>} AsyncPostVarsFunction
58+
*/
59+
4660
/**
4761
* @template {Record<string, any>} Vars - The type of variables passed to the page function
4862
* @template [PageReturn=any] PageReturn - The return type of the page function (defaults to any)
4963
* @typedef {PageFunction<Vars, PageReturn>} PageFunction
5064
*/
5165

66+
/**
67+
* @template {Record<string, any>} Vars - The type of variables passed to the async page function
68+
* @template [PageReturn=any] PageReturn - The return type of the page function (defaults to any)
69+
* @typedef {AsyncPageFunction<Vars, PageReturn>} AsyncPageFunction
70+
*/
71+
5272
/**
5373
* @template {Record<string, any>} Vars - The type of variables for the template function
5474
* @typedef {TemplateFunction<Vars>} TemplateFunction

lib/build-pages/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @import { BuilderOptions } from './page-builders/page-writer.js'
33
* @import { BuildStep } from '../builder.js'
4-
* @import { LayoutFunction } from './page-data.js'
4+
* @import { InternalLayoutFunction } from './page-data.js'
55
*/
66

77
import { Worker } from 'worker_threads'
@@ -37,11 +37,11 @@ const __dirname = import.meta.dirname
3737
*/
3838

3939
/**
40-
* @template T - The type of variables for the layout
40+
* @template {Record<string, any>} T - The type of variables for the layout
4141
* @template [U=any] U - The return type of the page function (defaults to any)
4242
* @template [V=string] V - The return type of the layout function (defaults to string)
4343
* @typedef ResolvedLayout
44-
* @property {LayoutFunction<T, U, V>} render - The layout function
44+
* @property {InternalLayoutFunction<T, U, V>} render - The layout function
4545
* @property {string} name - The name of the layout
4646
* @property {string | null} layoutStylePath - The string path to the layout style
4747
* @property {string | null} layoutClientPath - The string path to the layout client

lib/build-pages/page-builders/page-writer.js

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,53 @@ import { writeFile, mkdir } from 'fs/promises'
1919
*/
2020

2121
/**
22-
* pageLayout functions Can be used to type a name.layout.js file
22+
* Common parameters for page functions.
23+
*
24+
* @template {Record<string, any>} T - The type of variables passed to the page function
25+
* @template [U=any] U - The return type of the page function (defaults to any)
26+
* @typedef {object} PageFunctionParams
27+
* @property {T} vars - All default, global, layout, page, and builder vars shallow merged.
28+
* @property {string[]} [scripts] - Array of script URLs to include.
29+
* @property {string[]} [styles] - Array of stylesheet URLs to include.
30+
* @property {PageInfo} page - Info about the current page
31+
* @property {PageData<T, U, string>[]} pages - An array of info about every page
32+
* @property {Object<string, string>} [workers] - Map of worker names to their output paths
33+
*/
34+
35+
/**
36+
* Synchronous page function for rendering a page layout.
2337
*
2438
* @template {Record<string, any>} T - The type of variables passed to the page function
2539
* @template [U=any] U - The return type of the page function (defaults to any)
2640
* @callback PageFunction
27-
* @param {object} params - The parameters for the pageLayout.
28-
* @param {T} params.vars - All default, global, layout, page, and builder vars shallow merged.
29-
* @param {string[]} [params.scripts] - Array of script URLs to include.
30-
* @param {string[]} [params.styles] - Array of stylesheet URLs to include.
31-
* @param {PageInfo} params.page - Info about the current page
32-
* @param {PageData<T, U, string>[]} params.pages - An array of info about every page
33-
* @param {Object<string, string>} [params.workers] - Map of worker names to their output paths
34-
* @returns {Promise<U> | U} The rendered inner page thats compatible with its matched layout
41+
* @param {PageFunctionParams<T, U>} params - The parameters for the pageLayout.
42+
* @returns {U | Promise<U>} The rendered inner page thats compatible with its matched layout
43+
*/
44+
45+
/**
46+
* Asynchronous page function for rendering a page layout.
47+
*
48+
* @template {Record<string, any>} T - The type of variables passed to the page function
49+
* @template [U=any] U - The return type of the page function (defaults to any)
50+
* @callback AsyncPageFunction
51+
* @param {PageFunctionParams<T, U>} params - The parameters for the pageLayout.
52+
* @returns {Promise<U>} The rendered inner page thats compatible with its matched layout
53+
*/
54+
55+
/**
56+
* pageLayout functions can be used to type a name.layout.js file (can be sync or async).
57+
*
58+
* @template {Record<string, any>} T - The type of variables passed to the page function
59+
* @template [U=any] U - The return type of the page function (defaults to any)
60+
* @typedef {PageFunction<T, U> | AsyncPageFunction<T, U>} InternalPageFunction
3561
*/
3662

3763
/**
3864
* @template {Record<string, any>} T - The type of variables for the page
3965
* @template [U=any] U - The return type of the pageLayout function
4066
* @typedef PageBuilderResult
4167
* @property {object} vars - Any variables resolved by the builder
42-
* @property {PageFunction<T, U>} pageLayout - The function that returns the rendered page
68+
* @property {InternalPageFunction<T, U>} pageLayout - The function that returns the rendered page
4369
*/
4470

4571
/**

lib/build-pages/page-data.js

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ import pretty from 'pretty'
1717
* Resolves a layout from an ESM module.
1818
*
1919
* @function
20-
* @template T - The type of variables for the layout
20+
* @template {Record<string, any>} T - The type of variables for the layout
2121
* @template [U=any] U - The return type of the page function (defaults to any)
2222
* @template [V=string] V - The return type of the layout function (defaults to string)
2323
* @param {string} layoutPath - The string path to the layout ESM module.
24-
* @returns {Promise<LayoutFunction<T, U, V>>} The resolved layout exported as default from the module.
24+
* @returns {Promise<InternalLayoutFunction<T, U, V>>} The resolved layout exported as default from the module.
2525
*/
2626
export async function resolveLayout (layoutPath) {
2727
const { default: layout } = await import(layoutPath)
@@ -30,40 +30,98 @@ export async function resolveLayout (layoutPath) {
3030
}
3131

3232
/**
33-
* Callback for rendering a layout.
33+
* Common parameters for layout functions.
3434
*
35-
* @template T - The type of variables passed to the layout function
35+
* @template {Record<string, any>} T - The type of variables passed to the layout function
36+
* @template [U=any] U - The return type of the page function (defaults to any)
37+
* @template [V=string] V - The return type of the layout function (defaults to string)
38+
* @typedef {object} LayoutFunctionParams
39+
* @property {T} vars - All default, global, layout, page, and builder vars shallow merged.
40+
* @property {string[]} [scripts] - Array of script URLs to include.
41+
* @property {string[]} [styles] - Array of stylesheet URLs to include.
42+
* @property {U} children - The children content, either as a string or a render function.
43+
* @property {PageInfo} page - Info about the current page
44+
* @property {PageData<T, U, V>[]} pages - An array of info about every page
45+
* @property {Object<string, string>} [workers] - Map of worker names to their output paths
46+
*/
47+
48+
/**
49+
* Synchronous callback for rendering a layout.
50+
*
51+
* @template {Record<string, any>} T - The type of variables passed to the layout function
3652
* @template [U=any] U - The return type of the page function (defaults to any)
3753
* @template [V=string] V - The return type of the layout function (defaults to string)
3854
* @callback LayoutFunction
39-
* @param {object} params - The parameters for the layout.
40-
* @param {T} params.vars - All default, global, layout, page, and builder vars shallow merged.
41-
* @param {string[]} [params.scripts] - Array of script URLs to include.
42-
* @param {string[]} [params.styles] - Array of stylesheet URLs to include.
43-
* @param {U} params.children - The children content, either as a string or a render function.
44-
* @param {PageInfo} params.page - Info about the current page
45-
* @param {PageData<T, U, V>[]} params.pages - An array of info about every page
46-
* @param {Object<string, string>} [params.workers] - Map of worker names to their output paths
47-
* @returns {Promise<V> | V} The rendered content.
55+
* @param {LayoutFunctionParams<T, U, V>} params - The parameters for the layout.
56+
* @returns {V | Promise<V>} The rendered content.
57+
*/
58+
59+
/**
60+
* Asynchronous callback for rendering a layout.
61+
*
62+
* @template {Record<string, any>} T - The type of variables passed to the layout function
63+
* @template [U=any] U - The return type of the page function (defaults to any)
64+
* @template [V=string] V - The return type of the layout function (defaults to string)
65+
* @callback AsyncLayoutFunction
66+
* @param {LayoutFunctionParams<T, U, V>} params - The parameters for the layout.
67+
* @returns {Promise<V>} The rendered content.
68+
*/
69+
70+
/**
71+
* Callback for rendering a layout (can be sync or async).
72+
*
73+
* @template {Record<string, any>} T - The type of variables passed to the layout function
74+
* @template [U=any] U - The return type of the page function (defaults to any)
75+
* @template [V=string] V - The return type of the layout function (defaults to string)
76+
* @typedef {LayoutFunction<T, U, V> | AsyncLayoutFunction<T, U, V>} InternalLayoutFunction
4877
*/
4978

5079
/**
51-
* postVars functions Can be used to generate page vars but access all page data
80+
* Common parameters for postVars functions.
81+
*
82+
* @template {Record<string, any>} T - The type of variables for the page
83+
* @template [U=any] U - The return type of the page function (defaults to any)
84+
* @template [V=string] V - The return type of the layout function (defaults to string)
85+
* @typedef {object} PostVarsFunctionParams
86+
* @property {T} vars - All default, global, layout, page, and builder vars shallow merged.
87+
* @property {string[]} [scripts] - Array of script URLs to include.
88+
* @property {string[]} [styles] - Array of stylesheet URLs to include.
89+
* @property {PageInfo} page - Info about the current page
90+
* @property {PageData<T, U, V>[]} pages - An array of info about every page
91+
* @property {Object<string, string>} [workers] - Map of worker names to their output paths
92+
*/
93+
94+
/**
95+
* Synchronous postVars function to generate page vars with access to all page data.
5296
*
5397
* @template {Record<string, any>} T - The type of variables for the page
5498
* @template [U=any] U - The return type of the page function (defaults to any)
5599
* @template [V=string] V - The return type of the layout function (defaults to string)
56100
* @callback PostVarsFunction
57-
* @param {object} params - The parameters for the pageLayout.
58-
* @param {T} params.vars - All default, global, layout, page, and builder vars shallow merged.
59-
* @param {string[]} [params.scripts] - Array of script URLs to include.
60-
* @param {string[]} [params.styles] - Array of stylesheet URLs to include.
61-
* @param {PageInfo} params.page - Info about the current page
62-
* @param {PageData<T, U, V>[]} params.pages - An array of info about every page
63-
* @param {Object<string, string>} [params.workers] - Map of worker names to their output paths
101+
* @param {PostVarsFunctionParams<T, U, V>} params - The parameters for the postVars function.
102+
* @returns {T | Promise<T>} The rendered postVars
103+
*/
104+
105+
/**
106+
* Asynchronous postVars function to generate page vars with access to all page data.
107+
*
108+
* @template {Record<string, any>} T - The type of variables for the page
109+
* @template [U=any] U - The return type of the page function (defaults to any)
110+
* @template [V=string] V - The return type of the layout function (defaults to string)
111+
* @callback AsyncPostVarsFunction
112+
* @param {PostVarsFunctionParams<T, U, V>} params - The parameters for the postVars function.
64113
* @returns {Promise<T>} The rendered postVars
65114
*/
66115

116+
/**
117+
* postVars functions can be used to generate page vars but access all page data (can be sync or async).
118+
*
119+
* @template {Record<string, any>} T - The type of variables for the page
120+
* @template [U=any] U - The return type of the page function (defaults to any)
121+
* @template [V=string] V - The return type of the layout function (defaults to string)
122+
* @typedef {PostVarsFunction<T, U, V> | AsyncPostVarsFunction<T, U, V>} InternalPostVarsFunction
123+
*/
124+
67125
/**
68126
* Represents the data for a page.
69127
* @template {Record<string, any>} T - The type of variables for the page data
@@ -79,7 +137,7 @@ export class PageData {
79137
/** @type {object?} */ builderVars = null
80138
/** @type {string[]} */ styles = []
81139
/** @type {string[]} */ scripts = []
82-
/** @type {WorkerFiles|undefined} */ workerFiles = undefined
140+
/** @type {WorkerFiles} */ workerFiles = {}
83141
/** @type {boolean} */ #initialized = false
84142
/** @type {T?} */ #renderedPostVars = null
85143
/** @type {string?} */ #defaultStyle = null
@@ -138,14 +196,14 @@ export class PageData {
138196

139197
/**
140198
* Access web worker file paths associated with this page
141-
* @return {WorkerFiles|undefined} Map of worker names to their output paths
199+
* @return {WorkerFiles} Map of worker names to their output paths
142200
*/
143201
get workers () {
144202
return this.workerFiles
145203
}
146204

147205
/**
148-
* @type {PostVarsFunction<T, U, V>}
206+
* @type {AsyncPostVarsFunction<T, U, V>}
149207
*/
150208
async #renderPostVars ({ vars, styles, scripts, pages, page, workers }) {
151209
if (!this.#initialized) throw new Error('Initialize PageData before accessing renderPostVars')
@@ -218,7 +276,6 @@ export class PageData {
218276
// Initialize web workers if they exist
219277
if (pageInfo.workers) {
220278
/** @type {WorkerFiles} */
221-
this.workerFiles = {}
222279
for (const [workerName, workerFile] of Object.entries(pageInfo.workers)) {
223280
if (workerFile.outputRelname) {
224281
this.workerFiles[workerName] = `./${workerFile.outputName}`

lib/defaults/default.root.layout.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @import { LayoutFunction } from '../build-pages/page-data.js'
2+
* @import { LayoutFunction } from '../../index.js'
33
* @import { VNode } from 'preact'
44
*/
55
import { html } from 'htm/preact'

test-cases/general-features/src/blog/page.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { html } from 'htm/preact'
22
import { dirname, basename } from 'node:path'
33

44
/**
5-
* @type {import('../../../../index.js').LayoutFunction<{}>}
5+
* @type {import('../../../../index.js').InternalLayoutFunction<{}>}
66
*/
77
export default async function blogIndex ({
88
pages

test-cases/general-features/src/layouts/blog.layout.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { html } from 'htm/preact'
33

44
/**
55
* @template {Record<string, any>} T
6-
* @typedef {import('../../../../index.js').LayoutFunction<T>} LayoutFunction
6+
* @typedef {import('../../../../index.js').InternalLayoutFunction<T>} LayoutFunction
77
*/
88

99
/**

test-cases/general-features/src/layouts/root.layout.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { render } from 'preact-render-to-string'
33

44
/**
55
* @template {Record<string, any>} T
6-
* @typedef {import('../../../../index.js').LayoutFunction<T>} LayoutFunction
6+
* @typedef {import('../../../../index.js').InternalLayoutFunction<T>} LayoutFunction
77
*/
88

99
/**

0 commit comments

Comments
 (0)