@inglorious/ssx 0.4.0 → 0.4.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inglorious/ssx",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Server-Side-X. Xecution? Xperience? Who knows.",
5
5
  "author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
6
6
  "license": "MIT",
@@ -47,7 +47,7 @@
47
47
  "glob": "^13.0.0",
48
48
  "rollup-plugin-minify-template-literals": "^1.1.7",
49
49
  "vite": "^7.1.3",
50
- "@inglorious/web": "4.0.0"
50
+ "@inglorious/web": "4.0.1"
51
51
  },
52
52
  "devDependencies": {
53
53
  "prettier": "^3.6.2",
package/src/build.js CHANGED
@@ -27,7 +27,7 @@ export async function build(options = {}) {
27
27
  const store = await generateStore(pages, options)
28
28
 
29
29
  // Render all pages
30
- const renderedPages = await generatePages(store, pages, options)
30
+ const htmls = await renderPages(store, pages, options)
31
31
 
32
32
  // Write all pages to disk
33
33
  console.log("\nšŸ’¾ Writing files...\n")
@@ -35,10 +35,11 @@ export async function build(options = {}) {
35
35
  const app = generateApp(store, pages)
36
36
  await fs.writeFile(path.join(outDir, "main.js"), app, "utf-8")
37
37
 
38
- for (const { page, html } of renderedPages) {
38
+ pages.forEach(async (page, index) => {
39
+ const html = htmls[index]
39
40
  const filePath = await writePageToDisk(page.path, html, outDir)
40
41
  console.log(` āœ“ ${filePath}`)
41
- }
42
+ })
42
43
 
43
44
  // Bundle with Vite
44
45
  console.log("\nšŸ“¦ Bundling with Vite...\n")
@@ -50,10 +51,10 @@ export async function build(options = {}) {
50
51
 
51
52
  console.log("\n✨ Build complete!\n")
52
53
 
53
- return { pages: renderedPages.length, outDir }
54
+ return { pages: htmls.length, outDir }
54
55
  }
55
56
 
56
- async function generatePages(store, pages, options = {}) {
57
+ async function renderPages(store, pages, options = {}) {
57
58
  const { renderOptions } = options
58
59
 
59
60
  const renderedPages = []
@@ -62,11 +63,11 @@ async function generatePages(store, pages, options = {}) {
62
63
  console.log(` Rendering ${page.path}...`)
63
64
 
64
65
  const module = await import(pathToFileURL(page.filePath))
65
- const html = await renderPage(store, module, {
66
+ const html = await renderPage(store, page, module, {
66
67
  ...renderOptions,
67
68
  wrap: true,
68
69
  })
69
- renderedPages.push({ page, module, html })
70
+ renderedPages.push(html)
70
71
  }
71
72
 
72
73
  return renderedPages
package/src/dev.js CHANGED
@@ -48,7 +48,7 @@ export async function dev(options = {}) {
48
48
  if (!page) return next()
49
49
 
50
50
  const module = await viteServer.ssrLoadModule(page.filePath)
51
- const html = await renderPage(store, module, {
51
+ const html = await renderPage(store, page, module, {
52
52
  ...renderOptions,
53
53
  wrap: true,
54
54
  })
package/src/render.js CHANGED
@@ -1,31 +1,48 @@
1
1
  import { toHTML } from "./html.js"
2
2
  import { getModuleName } from "./module.js"
3
3
 
4
- export async function renderPage(store, pageModule, options) {
5
- const name = getModuleName(pageModule)
4
+ export async function renderPage(store, page, module, options = {}) {
5
+ const { title = "", meta = {}, scripts = [], styles = [] } = options
6
+
7
+ const name = getModuleName(module)
6
8
  const api = store._api
7
9
  const entity = api.getEntity(name)
8
10
 
9
- if (pageModule.load) {
10
- await pageModule.load(entity, store._api)
11
+ if (module.load) {
12
+ await module.load(entity, page, store._api)
13
+ }
14
+
15
+ const pageTitle = module.title
16
+ ? typeof module.title === "function"
17
+ ? module.title(entity, api)
18
+ : module.title
19
+ : title
20
+
21
+ const pageMeta = {
22
+ ...meta,
23
+ ...(typeof module.meta === "function"
24
+ ? module.meta(entity, api)
25
+ : (module.meta ?? {})),
11
26
  }
12
27
 
13
- const title =
14
- typeof pageModule.title === "function"
15
- ? pageModule.title(entity, api)
16
- : pageModule.title
17
- const meta =
18
- typeof options.meta === "function"
19
- ? options.meta(entity, api)
20
- : options.meta
21
- const scripts = pageModule.scripts
22
- const styles = pageModule.styles
28
+ const pageScripts = [
29
+ ...scripts,
30
+ ...(typeof module.scripts === "function"
31
+ ? module.scripts(entity, api)
32
+ : (module.scripts ?? [])),
33
+ ]
34
+ const pageStyles = [
35
+ ...styles,
36
+ ...(typeof module.styles === "function"
37
+ ? module.styles(entity, api)
38
+ : (module.styles ?? [])),
39
+ ]
23
40
 
24
41
  return toHTML(store, (api) => api.render(name, { allowType: true }), {
25
42
  ...options,
26
- title,
27
- meta,
28
- scripts,
29
- styles,
43
+ title: pageTitle,
44
+ meta: pageMeta,
45
+ scripts: pageScripts,
46
+ styles: pageStyles,
30
47
  })
31
48
  }
@@ -11,6 +11,7 @@ const PAGES_DIR = path.join(ROOT_DIR, "pages")
11
11
  const DEFAULT_OPTIONS = { stripLitMarkers: true }
12
12
 
13
13
  it("should render a static page fragment", async () => {
14
+ const page = { path: "/" }
14
15
  const module = await import(path.resolve(path.join(PAGES_DIR, "about.js")))
15
16
 
16
17
  const store = createStore({
@@ -18,42 +19,45 @@ it("should render a static page fragment", async () => {
18
19
  updateMode: "manual",
19
20
  })
20
21
 
21
- const html = await renderPage(store, module, DEFAULT_OPTIONS)
22
+ const html = await renderPage(store, page, module, DEFAULT_OPTIONS)
22
23
 
23
24
  expect(html).toMatchSnapshot()
24
25
  })
25
26
 
26
- it("should render a whole static page", async () => {
27
+ it("should render a page with entity", async () => {
28
+ const page = { path: "/about" }
27
29
  const module = await import(path.resolve(path.join(PAGES_DIR, "about.js")))
28
30
 
29
31
  const store = createStore({
30
32
  types: { about: module.about },
33
+ entities: { about: { type: "about", name: "Us" } },
31
34
  updateMode: "manual",
32
35
  })
33
36
 
34
- const html = await renderPage(store, module, {
35
- ...DEFAULT_OPTIONS,
36
- wrap: true,
37
- })
37
+ const html = await renderPage(store, page, module, DEFAULT_OPTIONS)
38
38
 
39
39
  expect(html).toMatchSnapshot()
40
40
  })
41
41
 
42
- it("should render a page with entity", async () => {
42
+ it("should render a page with metadata", async () => {
43
+ const page = { path: "/about" }
43
44
  const module = await import(path.resolve(path.join(PAGES_DIR, "about.js")))
44
45
 
45
46
  const store = createStore({
46
47
  types: { about: module.about },
47
- entities: { about: { type: "about", name: "Us" } },
48
48
  updateMode: "manual",
49
49
  })
50
50
 
51
- const html = await renderPage(store, module, DEFAULT_OPTIONS)
51
+ const html = await renderPage(store, page, module, {
52
+ ...DEFAULT_OPTIONS,
53
+ wrap: true,
54
+ })
52
55
 
53
56
  expect(html).toMatchSnapshot()
54
57
  })
55
58
 
56
59
  it("should render a page with pre-fetched data", async () => {
60
+ const page = { path: "/posts" }
57
61
  const module = await import(path.resolve(path.join(PAGES_DIR, "posts.js")))
58
62
 
59
63
  const store = createStore({
@@ -62,7 +66,7 @@ it("should render a page with pre-fetched data", async () => {
62
66
  updateMode: "manual",
63
67
  })
64
68
 
65
- const html = await renderPage(store, module, DEFAULT_OPTIONS)
69
+ const html = await renderPage(store, page, module, DEFAULT_OPTIONS)
66
70
 
67
71
  expect(html).toMatchSnapshot()
68
72
  })
package/src/router.js CHANGED
@@ -35,6 +35,7 @@ export async function getPages(pagesDir = "pages") {
35
35
  const params = extractParams(route, urlPath)
36
36
 
37
37
  pages.push({
38
+ pattern: route.pattern,
38
39
  path: urlPath,
39
40
  modulePath: route.modulePath,
40
41
  filePath: route.filePath,
@@ -51,7 +52,8 @@ export async function getPages(pagesDir = "pages") {
51
52
  } else {
52
53
  // Static route - add directly
53
54
  pages.push({
54
- path: route.pattern === "" ? "/" : route.pattern,
55
+ pattern: route.pattern,
56
+ path: route.pattern || "/",
55
57
  modulePath: route.modulePath,
56
58
  filePath: route.filePath,
57
59
  moduleName,
@@ -6,9 +6,14 @@
6
6
  */
7
7
  export function generateApp(store, pages) {
8
8
  // Collect all unique page modules and their exports
9
- const routes = pages.map(
10
- (page) => ` "${page.path}": () => import("@/pages/${page.modulePath}")`,
11
- )
9
+ const routes = pages
10
+ .filter((page, index) => {
11
+ return pages.findIndex((p) => p.pattern === page.pattern) === index
12
+ })
13
+ .map(
14
+ (page) =>
15
+ ` "${page.pattern}": () => import("@/pages/${page.modulePath}")`,
16
+ )
12
17
 
13
18
  return `import { createDevtools, createStore, mount } from "@inglorious/web"
14
19
  import { getRoute, router, setRoutes } from "@inglorious/web/router"
@@ -37,7 +42,7 @@ setRoutes({
37
42
  ${routes.join(",\n")}
38
43
  })
39
44
 
40
- const module = await getRoute(page.path)()
45
+ const module = await getRoute(page.pattern)()
41
46
  const type = module[page.moduleName]
42
47
  types[page.moduleName] = type
43
48