From 2ea519b9ce27393e7d961b098c518413c67b958b Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Mon, 25 Nov 2024 20:52:27 +0100 Subject: [PATCH 01/20] feat: create build-config script --- packages/tuono/bin/build-config.js | 5 + packages/tuono/package.json | 13 +- packages/tuono/src/build/index.ts | 235 +++++++++++++++++------------ packages/tuono/src/config/index.ts | 1 + packages/tuono/src/config/types.ts | 5 + packages/tuono/vite.config.ts | 1 + 6 files changed, 166 insertions(+), 94 deletions(-) create mode 100644 packages/tuono/bin/build-config.js create mode 100644 packages/tuono/src/config/index.ts create mode 100644 packages/tuono/src/config/types.ts diff --git a/packages/tuono/bin/build-config.js b/packages/tuono/bin/build-config.js new file mode 100644 index 00000000..604c19eb --- /dev/null +++ b/packages/tuono/bin/build-config.js @@ -0,0 +1,5 @@ +#!/usr/bin/env node + +import { buildConfig } from '../dist/esm/build/index.js' + +buildConfig() diff --git a/packages/tuono/package.json b/packages/tuono/package.json index b8d80e00..f3027dba 100644 --- a/packages/tuono/package.json +++ b/packages/tuono/package.json @@ -26,6 +26,16 @@ "default": "./dist/cjs/build/index.js" } }, + "./config": { + "import": { + "types": "./dist/esm/config/index.d.ts", + "default": "./dist/esm/config/index.js" + }, + "require": { + "types": "./dist/cjs/config/index.d.ts", + "default": "./dist/cjs/config/index.js" + } + }, "./ssr": { "import": { "types": "./dist/esm/ssr/index.d.ts", @@ -61,7 +71,8 @@ "bin": { "tuono-dev-ssr": "./bin/dev-ssr.js", "tuono-dev-watch": "./bin/watch.js", - "tuono-build-prod": "./bin/build-prod.js" + "tuono-build-prod": "./bin/build-prod.js", + "tuono-build-config": "./bin/build-config.js" }, "files": [ "dist", diff --git a/packages/tuono/src/build/index.ts b/packages/tuono/src/build/index.ts index c91769c9..f234fd70 100644 --- a/packages/tuono/src/build/index.ts +++ b/packages/tuono/src/build/index.ts @@ -4,109 +4,158 @@ import ViteFsRouter from 'tuono-fs-router-vite-plugin' import { LazyLoadingPlugin } from 'tuono-lazy-fn-vite-plugin' import mdx from '@mdx-js/rollup' -const BASE_CONFIG: InlineConfig = { - root: '.tuono', - logLevel: 'silent', - publicDir: '../public', - cacheDir: 'cache', - envDir: '../', - optimizeDeps: { - exclude: ['@mdx-js/react'], - }, - plugins: [ - { enforce: 'pre', ...mdx({ providerImportSource: '@mdx-js/react' }) }, - // @ts-ignore: TS configuration issue. - react({ include: /\.(jsx|js|mdx|md|tsx|ts)$/ }), - ViteFsRouter(), - LazyLoadingPlugin(), - ], -} +import { TuonoConfig } from '../config' const VITE_PORT = 3001 +const loadConfig = async (): Promise => { + try { + return await import(`${process.cwd()}/.tuono/config/config.js`) + } catch { + return {} + } +} + +const BASE_CONFIG: InlineConfig = { + root: '.tuono', + logLevel: 'silent', + publicDir: '../public', + cacheDir: 'cache', + envDir: '../', + optimizeDeps: { + exclude: ['@mdx-js/react'], + }, + plugins: [ + { enforce: 'pre', ...mdx({ providerImportSource: '@mdx-js/react' }) }, + // @ts-ignore: TS configuration issue. + react({ include: /\.(jsx|js|mdx|md|tsx|ts)$/ }), + ViteFsRouter(), + LazyLoadingPlugin(), + ], +} + export function developmentSSRBundle() { - ;(async () => { - await build({ - ...BASE_CONFIG, - build: { - ssr: true, - minify: false, - outDir: 'server', - emptyOutDir: true, - rollupOptions: { - input: './.tuono/server-main.tsx', - // Silent all logs - onLog() {}, - output: { - entryFileNames: 'dev-server.js', - format: 'iife', - }, - }, - }, - ssr: { - target: 'webworker', - noExternal: true, - }, - }) - })() + ; (async () => { + const config = await loadConfig() + await build({ + resolve: { + alias: config.vite?.alias || {}, + }, + ...BASE_CONFIG, + build: { + ssr: true, + minify: false, + outDir: 'server', + emptyOutDir: true, + rollupOptions: { + input: './.tuono/server-main.tsx', + // Silent all logs + onLog() { }, + output: { + entryFileNames: 'dev-server.js', + format: 'iife', + }, + }, + }, + ssr: { + target: 'webworker', + noExternal: true, + }, + }) + })() } export function developmentCSRWatch() { - ;(async () => { - const server = await createServer({ - ...BASE_CONFIG, - // Entry point for the development vite proxy - base: '/vite-server/', + ; (async () => { + const config = await loadConfig() + const server = await createServer({ + resolve: { + alias: config.vite?.alias || {}, + }, + ...BASE_CONFIG, + // Entry point for the development vite proxy + base: '/vite-server/', - server: { - port: VITE_PORT, - strictPort: true, - }, - build: { - manifest: true, - emptyOutDir: true, - rollupOptions: { - input: './.tuono/client-main.tsx', - }, - }, - }) - await server.listen() - })() + server: { + port: VITE_PORT, + strictPort: true, + }, + build: { + manifest: true, + emptyOutDir: true, + rollupOptions: { + input: './.tuono/client-main.tsx', + }, + }, + }) + await server.listen() + })() } export function buildProd() { - ;(async () => { - await build({ - ...BASE_CONFIG, - build: { - manifest: true, - emptyOutDir: true, - outDir: '../out/client', - rollupOptions: { - input: './.tuono/client-main.tsx', - }, - }, - }) + ; (async () => { + const config = await loadConfig() + await build({ + resolve: { + alias: config.vite?.alias || {}, + }, + ...BASE_CONFIG, + build: { + manifest: true, + emptyOutDir: true, + outDir: '../out/client', + rollupOptions: { + input: './.tuono/client-main.tsx', + }, + }, + }) + + await build({ + resolve: { + alias: config.vite?.alias || {}, + }, + ...BASE_CONFIG, + build: { + ssr: true, + minify: true, + outDir: '../out/server', + emptyOutDir: true, + rollupOptions: { + input: './.tuono/server-main.tsx', + output: { + entryFileNames: 'prod-server.js', + format: 'iife', + }, + }, + }, + ssr: { + target: 'webworker', + noExternal: true, + }, + }) + })() +} - await build({ - ...BASE_CONFIG, - build: { - ssr: true, - minify: true, - outDir: '../out/server', - emptyOutDir: true, - rollupOptions: { - input: './.tuono/server-main.tsx', - output: { - entryFileNames: 'prod-server.js', - format: 'iife', - }, - }, - }, - ssr: { - target: 'webworker', - noExternal: true, - }, - }) - })() +export function buildConfig() { + ; (async () => { + await build({ + root: '.tuono', + logLevel: 'silent', + cacheDir: 'cache', + envDir: '../', + build: { + ssr: true, + outDir: 'config', + emptyOutDir: true, + rollupOptions: { + input: './tuono.config.ts', + output: { + entryFileNames: 'config.js', + name: 'config', + format: 'cjs', + }, + }, + }, + }) + })() } diff --git a/packages/tuono/src/config/index.ts b/packages/tuono/src/config/index.ts new file mode 100644 index 00000000..b7c6b20d --- /dev/null +++ b/packages/tuono/src/config/index.ts @@ -0,0 +1 @@ +export type { TuonoConfig } from './types' diff --git a/packages/tuono/src/config/types.ts b/packages/tuono/src/config/types.ts new file mode 100644 index 00000000..e85fd201 --- /dev/null +++ b/packages/tuono/src/config/types.ts @@ -0,0 +1,5 @@ +export interface TuonoConfig { + vite?: { + alias?: Record + } +} diff --git a/packages/tuono/vite.config.ts b/packages/tuono/vite.config.ts index d260b490..854eb189 100644 --- a/packages/tuono/vite.config.ts +++ b/packages/tuono/vite.config.ts @@ -14,6 +14,7 @@ export default mergeConfig( entry: [ './src/index.ts', './src/build/index.ts', + './src/config/index.ts', './src/ssr/index.tsx', './src/hydration/index.tsx', ], From 140666495983b382ad8e9a2d8133b096c7eb984c Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Mon, 25 Nov 2024 20:59:53 +0100 Subject: [PATCH 02/20] refactor: cleanup vite build functions --- packages/tuono/src/build/index.ts | 37 +++++++++++++------------------ packages/tuono/src/build/utils.ts | 15 +++++++++++++ 2 files changed, 30 insertions(+), 22 deletions(-) create mode 100644 packages/tuono/src/build/utils.ts diff --git a/packages/tuono/src/build/index.ts b/packages/tuono/src/build/index.ts index f234fd70..596ab6c3 100644 --- a/packages/tuono/src/build/index.ts +++ b/packages/tuono/src/build/index.ts @@ -3,19 +3,10 @@ import react from '@vitejs/plugin-react-swc' import ViteFsRouter from 'tuono-fs-router-vite-plugin' import { LazyLoadingPlugin } from 'tuono-lazy-fn-vite-plugin' import mdx from '@mdx-js/rollup' - -import { TuonoConfig } from '../config' +import { loadConfig, blockingAsync } from './utils' const VITE_PORT = 3001 -const loadConfig = async (): Promise => { - try { - return await import(`${process.cwd()}/.tuono/config/config.js`) - } catch { - return {} - } -} - const BASE_CONFIG: InlineConfig = { root: '.tuono', logLevel: 'silent', @@ -34,8 +25,8 @@ const BASE_CONFIG: InlineConfig = { ], } -export function developmentSSRBundle() { - ; (async () => { +const developmentSSRBundle = () => { + blockingAsync(async () => { const config = await loadConfig() await build({ resolve: { @@ -62,11 +53,11 @@ export function developmentSSRBundle() { noExternal: true, }, }) - })() + }) } -export function developmentCSRWatch() { - ; (async () => { +const developmentCSRWatch = () => { + blockingAsync(async () => { const config = await loadConfig() const server = await createServer({ resolve: { @@ -89,11 +80,11 @@ export function developmentCSRWatch() { }, }) await server.listen() - })() + }) } -export function buildProd() { - ; (async () => { +const buildProd = () => { + blockingAsync(async () => { const config = await loadConfig() await build({ resolve: { @@ -133,11 +124,11 @@ export function buildProd() { noExternal: true, }, }) - })() + }) } -export function buildConfig() { - ; (async () => { +const buildConfig = () => { + blockingAsync(async () => { await build({ root: '.tuono', logLevel: 'silent', @@ -157,5 +148,7 @@ export function buildConfig() { }, }, }) - })() + }) } + +export { buildProd, buildConfig, developmentCSRWatch, developmentSSRBundle } diff --git a/packages/tuono/src/build/utils.ts b/packages/tuono/src/build/utils.ts new file mode 100644 index 00000000..51a0192f --- /dev/null +++ b/packages/tuono/src/build/utils.ts @@ -0,0 +1,15 @@ +import { TuonoConfig } from '../config' + +export const loadConfig = async (): Promise => { + try { + return await import(`${process.cwd()}/.tuono/config/config.js`) + } catch { + return {} + } +} + +export const blockingAsync = (callback: () => Promise) => { + ; (async () => { + await callback() + })() +} From 35f0e26b2b971a437805d7bfef16efc999dcfe04 Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Mon, 25 Nov 2024 21:13:42 +0100 Subject: [PATCH 03/20] feat: add tuono.config.ts to the examples --- examples/tuono-app/tsconfig.json | 2 +- examples/tuono-app/tuono.config.ts | 9 +++++++++ examples/tuono-tutorial/tsconfig.json | 2 +- examples/tuono-tutorial/tuono.config.ts | 9 +++++++++ examples/with-mdx/tsconfig.json | 2 +- examples/with-mdx/tuono.config.ts | 9 +++++++++ 6 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 examples/tuono-app/tuono.config.ts create mode 100644 examples/tuono-tutorial/tuono.config.ts create mode 100644 examples/with-mdx/tuono.config.ts diff --git a/examples/tuono-app/tsconfig.json b/examples/tuono-app/tsconfig.json index a7fc6fbf..8d08b177 100644 --- a/examples/tuono-app/tsconfig.json +++ b/examples/tuono-app/tsconfig.json @@ -20,6 +20,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, - "include": ["src"], + "include": ["src", "tuono.config.ts"], "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/examples/tuono-app/tuono.config.ts b/examples/tuono-app/tuono.config.ts new file mode 100644 index 00000000..8073f648 --- /dev/null +++ b/examples/tuono-app/tuono.config.ts @@ -0,0 +1,9 @@ +import type { TuonoConfig } from 'tuono/config' + +const config: TuonoConfig = { + vite: { + alias: { 'my-alias': 'my-alias' }, + }, +} + +export default config diff --git a/examples/tuono-tutorial/tsconfig.json b/examples/tuono-tutorial/tsconfig.json index a7fc6fbf..8d08b177 100644 --- a/examples/tuono-tutorial/tsconfig.json +++ b/examples/tuono-tutorial/tsconfig.json @@ -20,6 +20,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, - "include": ["src"], + "include": ["src", "tuono.config.ts"], "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/examples/tuono-tutorial/tuono.config.ts b/examples/tuono-tutorial/tuono.config.ts new file mode 100644 index 00000000..8073f648 --- /dev/null +++ b/examples/tuono-tutorial/tuono.config.ts @@ -0,0 +1,9 @@ +import type { TuonoConfig } from 'tuono/config' + +const config: TuonoConfig = { + vite: { + alias: { 'my-alias': 'my-alias' }, + }, +} + +export default config diff --git a/examples/with-mdx/tsconfig.json b/examples/with-mdx/tsconfig.json index a7fc6fbf..8d08b177 100644 --- a/examples/with-mdx/tsconfig.json +++ b/examples/with-mdx/tsconfig.json @@ -20,6 +20,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, - "include": ["src"], + "include": ["src", "tuono.config.ts"], "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/examples/with-mdx/tuono.config.ts b/examples/with-mdx/tuono.config.ts new file mode 100644 index 00000000..8073f648 --- /dev/null +++ b/examples/with-mdx/tuono.config.ts @@ -0,0 +1,9 @@ +import type { TuonoConfig } from 'tuono/config' + +const config: TuonoConfig = { + vite: { + alias: { 'my-alias': 'my-alias' }, + }, +} + +export default config From bb4e800100ff8140546e226305d1ade3cc1ca702 Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Mon, 25 Nov 2024 21:14:08 +0100 Subject: [PATCH 04/20] fix: formatting --- packages/tuono/src/build/index.ts | 254 +++++++++++++++--------------- packages/tuono/src/build/utils.ts | 16 +- 2 files changed, 135 insertions(+), 135 deletions(-) diff --git a/packages/tuono/src/build/index.ts b/packages/tuono/src/build/index.ts index 596ab6c3..c42c4502 100644 --- a/packages/tuono/src/build/index.ts +++ b/packages/tuono/src/build/index.ts @@ -8,147 +8,147 @@ import { loadConfig, blockingAsync } from './utils' const VITE_PORT = 3001 const BASE_CONFIG: InlineConfig = { - root: '.tuono', - logLevel: 'silent', - publicDir: '../public', - cacheDir: 'cache', - envDir: '../', - optimizeDeps: { - exclude: ['@mdx-js/react'], - }, - plugins: [ - { enforce: 'pre', ...mdx({ providerImportSource: '@mdx-js/react' }) }, - // @ts-ignore: TS configuration issue. - react({ include: /\.(jsx|js|mdx|md|tsx|ts)$/ }), - ViteFsRouter(), - LazyLoadingPlugin(), - ], + root: '.tuono', + logLevel: 'silent', + publicDir: '../public', + cacheDir: 'cache', + envDir: '../', + optimizeDeps: { + exclude: ['@mdx-js/react'], + }, + plugins: [ + { enforce: 'pre', ...mdx({ providerImportSource: '@mdx-js/react' }) }, + // @ts-ignore: TS configuration issue. + react({ include: /\.(jsx|js|mdx|md|tsx|ts)$/ }), + ViteFsRouter(), + LazyLoadingPlugin(), + ], } const developmentSSRBundle = () => { - blockingAsync(async () => { - const config = await loadConfig() - await build({ - resolve: { - alias: config.vite?.alias || {}, - }, - ...BASE_CONFIG, - build: { - ssr: true, - minify: false, - outDir: 'server', - emptyOutDir: true, - rollupOptions: { - input: './.tuono/server-main.tsx', - // Silent all logs - onLog() { }, - output: { - entryFileNames: 'dev-server.js', - format: 'iife', - }, - }, - }, - ssr: { - target: 'webworker', - noExternal: true, - }, - }) - }) + blockingAsync(async () => { + const config = await loadConfig() + await build({ + resolve: { + alias: config.vite?.alias || {}, + }, + ...BASE_CONFIG, + build: { + ssr: true, + minify: false, + outDir: 'server', + emptyOutDir: true, + rollupOptions: { + input: './.tuono/server-main.tsx', + // Silent all logs + onLog() {}, + output: { + entryFileNames: 'dev-server.js', + format: 'iife', + }, + }, + }, + ssr: { + target: 'webworker', + noExternal: true, + }, + }) + }) } const developmentCSRWatch = () => { - blockingAsync(async () => { - const config = await loadConfig() - const server = await createServer({ - resolve: { - alias: config.vite?.alias || {}, - }, - ...BASE_CONFIG, - // Entry point for the development vite proxy - base: '/vite-server/', + blockingAsync(async () => { + const config = await loadConfig() + const server = await createServer({ + resolve: { + alias: config.vite?.alias || {}, + }, + ...BASE_CONFIG, + // Entry point for the development vite proxy + base: '/vite-server/', - server: { - port: VITE_PORT, - strictPort: true, - }, - build: { - manifest: true, - emptyOutDir: true, - rollupOptions: { - input: './.tuono/client-main.tsx', - }, - }, - }) - await server.listen() - }) + server: { + port: VITE_PORT, + strictPort: true, + }, + build: { + manifest: true, + emptyOutDir: true, + rollupOptions: { + input: './.tuono/client-main.tsx', + }, + }, + }) + await server.listen() + }) } const buildProd = () => { - blockingAsync(async () => { - const config = await loadConfig() - await build({ - resolve: { - alias: config.vite?.alias || {}, - }, - ...BASE_CONFIG, - build: { - manifest: true, - emptyOutDir: true, - outDir: '../out/client', - rollupOptions: { - input: './.tuono/client-main.tsx', - }, - }, - }) + blockingAsync(async () => { + const config = await loadConfig() + await build({ + resolve: { + alias: config.vite?.alias || {}, + }, + ...BASE_CONFIG, + build: { + manifest: true, + emptyOutDir: true, + outDir: '../out/client', + rollupOptions: { + input: './.tuono/client-main.tsx', + }, + }, + }) - await build({ - resolve: { - alias: config.vite?.alias || {}, - }, - ...BASE_CONFIG, - build: { - ssr: true, - minify: true, - outDir: '../out/server', - emptyOutDir: true, - rollupOptions: { - input: './.tuono/server-main.tsx', - output: { - entryFileNames: 'prod-server.js', - format: 'iife', - }, - }, - }, - ssr: { - target: 'webworker', - noExternal: true, - }, - }) - }) + await build({ + resolve: { + alias: config.vite?.alias || {}, + }, + ...BASE_CONFIG, + build: { + ssr: true, + minify: true, + outDir: '../out/server', + emptyOutDir: true, + rollupOptions: { + input: './.tuono/server-main.tsx', + output: { + entryFileNames: 'prod-server.js', + format: 'iife', + }, + }, + }, + ssr: { + target: 'webworker', + noExternal: true, + }, + }) + }) } const buildConfig = () => { - blockingAsync(async () => { - await build({ - root: '.tuono', - logLevel: 'silent', - cacheDir: 'cache', - envDir: '../', - build: { - ssr: true, - outDir: 'config', - emptyOutDir: true, - rollupOptions: { - input: './tuono.config.ts', - output: { - entryFileNames: 'config.js', - name: 'config', - format: 'cjs', - }, - }, - }, - }) - }) + blockingAsync(async () => { + await build({ + root: '.tuono', + logLevel: 'silent', + cacheDir: 'cache', + envDir: '../', + build: { + ssr: true, + outDir: 'config', + emptyOutDir: true, + rollupOptions: { + input: './tuono.config.ts', + output: { + entryFileNames: 'config.js', + name: 'config', + format: 'cjs', + }, + }, + }, + }) + }) } export { buildProd, buildConfig, developmentCSRWatch, developmentSSRBundle } diff --git a/packages/tuono/src/build/utils.ts b/packages/tuono/src/build/utils.ts index 51a0192f..f22f6974 100644 --- a/packages/tuono/src/build/utils.ts +++ b/packages/tuono/src/build/utils.ts @@ -1,15 +1,15 @@ import { TuonoConfig } from '../config' export const loadConfig = async (): Promise => { - try { - return await import(`${process.cwd()}/.tuono/config/config.js`) - } catch { - return {} - } + try { + return await import(`${process.cwd()}/.tuono/config/config.js`) + } catch { + return {} + } } export const blockingAsync = (callback: () => Promise) => { - ; (async () => { - await callback() - })() + ;(async () => { + await callback() + })() } From 9b1ca735bd1e81179f73b55829ea38c49cad68d4 Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Thu, 28 Nov 2024 18:35:13 +0100 Subject: [PATCH 05/20] feat: load alias option type from vite --- packages/tuono/src/config/types.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/tuono/src/config/types.ts b/packages/tuono/src/config/types.ts index e85fd201..06a29e27 100644 --- a/packages/tuono/src/config/types.ts +++ b/packages/tuono/src/config/types.ts @@ -1,5 +1,7 @@ +import type { AliasOptions } from 'vite' + export interface TuonoConfig { vite?: { - alias?: Record + alias?: AliasOptions } } From 2fd7413bf2b63d0e96f1a103ce1252f606b167c8 Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Thu, 28 Nov 2024 19:04:16 +0100 Subject: [PATCH 06/20] feat: prevent wrong file paths --- packages/tuono/src/build/index.ts | 156 +++++++++++++++-------------- packages/tuono/src/build/utils.ts | 3 +- packages/tuono/src/config/index.ts | 3 + packages/tuono/src/config/path.ts | 10 ++ 4 files changed, 95 insertions(+), 77 deletions(-) create mode 100644 packages/tuono/src/config/path.ts diff --git a/packages/tuono/src/build/index.ts b/packages/tuono/src/build/index.ts index c42c4502..f622ddd6 100644 --- a/packages/tuono/src/build/index.ts +++ b/packages/tuono/src/build/index.ts @@ -1,4 +1,4 @@ -import { build, createServer, InlineConfig } from 'vite' +import { build, createServer, InlineConfig, mergeConfig } from 'vite' import react from '@vitejs/plugin-react-swc' import ViteFsRouter from 'tuono-fs-router-vite-plugin' import { LazyLoadingPlugin } from 'tuono-lazy-fn-vite-plugin' @@ -28,57 +28,59 @@ const BASE_CONFIG: InlineConfig = { const developmentSSRBundle = () => { blockingAsync(async () => { const config = await loadConfig() - await build({ - resolve: { - alias: config.vite?.alias || {}, - }, - ...BASE_CONFIG, - build: { - ssr: true, - minify: false, - outDir: 'server', - emptyOutDir: true, - rollupOptions: { - input: './.tuono/server-main.tsx', - // Silent all logs - onLog() {}, - output: { - entryFileNames: 'dev-server.js', - format: 'iife', + await build( + mergeConfig(BASE_CONFIG, { + resolve: { + alias: config.vite?.alias || {}, + }, + build: { + ssr: true, + minify: false, + outDir: 'server', + emptyOutDir: true, + rollupOptions: { + input: './.tuono/server-main.tsx', + // Silent all logs + onLog() {}, + output: { + entryFileNames: 'dev-server.js', + format: 'iife', + }, }, }, - }, - ssr: { - target: 'webworker', - noExternal: true, - }, - }) + ssr: { + target: 'webworker', + noExternal: true, + }, + }), + ) }) } const developmentCSRWatch = () => { blockingAsync(async () => { const config = await loadConfig() - const server = await createServer({ - resolve: { - alias: config.vite?.alias || {}, - }, - ...BASE_CONFIG, - // Entry point for the development vite proxy - base: '/vite-server/', + const server = await createServer( + mergeConfig(BASE_CONFIG, { + resolve: { + alias: config.vite?.alias || {}, + }, + // Entry point for the development vite proxy + base: '/vite-server/', - server: { - port: VITE_PORT, - strictPort: true, - }, - build: { - manifest: true, - emptyOutDir: true, - rollupOptions: { - input: './.tuono/client-main.tsx', + server: { + port: VITE_PORT, + strictPort: true, }, - }, - }) + build: { + manifest: true, + emptyOutDir: true, + rollupOptions: { + input: './.tuono/client-main.tsx', + }, + }, + }), + ) await server.listen() }) } @@ -86,44 +88,46 @@ const developmentCSRWatch = () => { const buildProd = () => { blockingAsync(async () => { const config = await loadConfig() - await build({ - resolve: { - alias: config.vite?.alias || {}, - }, - ...BASE_CONFIG, - build: { - manifest: true, - emptyOutDir: true, - outDir: '../out/client', - rollupOptions: { - input: './.tuono/client-main.tsx', + await build( + mergeConfig(BASE_CONFIG, { + resolve: { + alias: config.vite?.alias || {}, }, - }, - }) + build: { + manifest: true, + emptyOutDir: true, + outDir: '../out/client', + rollupOptions: { + input: './.tuono/client-main.tsx', + }, + }, + }), + ) - await build({ - resolve: { - alias: config.vite?.alias || {}, - }, - ...BASE_CONFIG, - build: { - ssr: true, - minify: true, - outDir: '../out/server', - emptyOutDir: true, - rollupOptions: { - input: './.tuono/server-main.tsx', - output: { - entryFileNames: 'prod-server.js', - format: 'iife', + await build( + mergeConfig(BASE_CONFIG, { + resolve: { + alias: config.vite?.alias || {}, + }, + build: { + ssr: true, + minify: true, + outDir: '../out/server', + emptyOutDir: true, + rollupOptions: { + input: './.tuono/server-main.tsx', + output: { + entryFileNames: 'prod-server.js', + format: 'iife', + }, }, }, - }, - ssr: { - target: 'webworker', - noExternal: true, - }, - }) + ssr: { + target: 'webworker', + noExternal: true, + }, + }), + ) }) } diff --git a/packages/tuono/src/build/utils.ts b/packages/tuono/src/build/utils.ts index f22f6974..bce61514 100644 --- a/packages/tuono/src/build/utils.ts +++ b/packages/tuono/src/build/utils.ts @@ -2,7 +2,8 @@ import { TuonoConfig } from '../config' export const loadConfig = async (): Promise => { try { - return await import(`${process.cwd()}/.tuono/config/config.js`) + const configFile = await import(`${process.cwd()}/.tuono/config/config.js`) + return configFile.default } catch { return {} } diff --git a/packages/tuono/src/config/index.ts b/packages/tuono/src/config/index.ts index b7c6b20d..a4012d94 100644 --- a/packages/tuono/src/config/index.ts +++ b/packages/tuono/src/config/index.ts @@ -1 +1,4 @@ export type { TuonoConfig } from './types' +import path from './path' + +export { path } diff --git a/packages/tuono/src/config/path.ts b/packages/tuono/src/config/path.ts new file mode 100644 index 00000000..ea50df7e --- /dev/null +++ b/packages/tuono/src/config/path.ts @@ -0,0 +1,10 @@ +/** + * Return the string cleared by the config path + */ +const join = (base: string, folder: string): string => { + return base.replace('.tuono/config', '').concat(folder.replace('./', '')) +} + +export default { + join, +} From 0b1ec13da84e70d13a52f22a6978cec6a23269f5 Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Thu, 28 Nov 2024 19:15:59 +0100 Subject: [PATCH 07/20] feat: build config on dev and build commands --- crates/tuono/src/app.rs | 13 +++++++++++++ crates/tuono/src/cli.rs | 7 ++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/crates/tuono/src/app.rs b/crates/tuono/src/app.rs index dd813943..f41922fd 100644 --- a/crates/tuono/src/app.rs +++ b/crates/tuono/src/app.rs @@ -21,11 +21,17 @@ const ROUTES_FOLDER_PATH: &str = "\\src\\routes"; #[cfg(target_os = "windows")] const BUILD_JS_SCRIPT: &str = ".\\node_modules\\.bin\\tuono-build-prod.cmd"; +#[cfg(target_os = "windows")] +const BUILD_TUONO_CONFIG: &str = ".\\node_modules\\.bin\\tuono-build-prod.cmd"; + #[cfg(not(target_os = "windows"))] const ROUTES_FOLDER_PATH: &str = "/src/routes"; #[cfg(not(target_os = "windows"))] const BUILD_JS_SCRIPT: &str = "./node_modules/.bin/tuono-build-prod"; +#[cfg(not(target_os = "windows"))] +const BUILD_TUONO_CONFIG: &str = "./node_modules/.bin/tuono-build-config"; + #[derive(Debug)] pub struct App { pub route_map: HashMap, @@ -147,6 +153,13 @@ impl App { .expect("Failed to run the rust server") } + pub fn build_tuono_config(&self) -> Result { + Command::new(BUILD_TUONO_CONFIG) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + } pub fn get_used_http_methods(&self) -> HashSet { let mut acc = HashSet::new(); diff --git a/crates/tuono/src/cli.rs b/crates/tuono/src/cli.rs index 6703f09c..2029d7dc 100644 --- a/crates/tuono/src/cli.rs +++ b/crates/tuono/src/cli.rs @@ -87,7 +87,9 @@ pub fn app() -> std::io::Result<()> { Actions::Dev => { check_ports(Mode::Dev); - let _ = init_tuono_folder(Mode::Dev)?; + let app = init_tuono_folder(Mode::Dev)?; + app.build_tuono_config() + .expect("Failed to build tuono.config.ts"); watch::watch().unwrap(); } @@ -105,6 +107,9 @@ pub fn app() -> std::io::Result<()> { return Ok(()); } + app.build_tuono_config() + .expect("Failed to build tuono.config.ts"); + app.build_react_prod(); if ssg { From 658411fe93b79c0ec6edb529228316ff3de7595e Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Thu, 28 Nov 2024 19:17:23 +0100 Subject: [PATCH 08/20] feat: add log when fail to load tuono.config.ts --- packages/tuono/src/build/utils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/tuono/src/build/utils.ts b/packages/tuono/src/build/utils.ts index bce61514..3471ff5b 100644 --- a/packages/tuono/src/build/utils.ts +++ b/packages/tuono/src/build/utils.ts @@ -5,6 +5,7 @@ export const loadConfig = async (): Promise => { const configFile = await import(`${process.cwd()}/.tuono/config/config.js`) return configFile.default } catch { + console.error('Failed to load tuono.config.ts') return {} } } From caa19a900d66bcf2f263d6a8d7a5e465863cf5d4 Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Thu, 28 Nov 2024 19:21:46 +0100 Subject: [PATCH 09/20] feat: add configs to examples --- examples/tuono-app/tsconfig.json | 5 ++++- examples/tuono-app/tuono.config.ts | 5 ++++- examples/tuono-tutorial/tsconfig.json | 5 ++++- examples/tuono-tutorial/tuono.config.ts | 5 ++++- examples/with-mdx/tsconfig.json | 5 ++++- examples/with-mdx/tuono.config.ts | 5 ++++- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/examples/tuono-app/tsconfig.json b/examples/tuono-app/tsconfig.json index 8d08b177..e7ce4768 100644 --- a/examples/tuono-app/tsconfig.json +++ b/examples/tuono-app/tsconfig.json @@ -18,7 +18,10 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "paths": { + "@/*": ["./src/*"] + } }, "include": ["src", "tuono.config.ts"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/examples/tuono-app/tuono.config.ts b/examples/tuono-app/tuono.config.ts index 8073f648..bc440a23 100644 --- a/examples/tuono-app/tuono.config.ts +++ b/examples/tuono-app/tuono.config.ts @@ -1,8 +1,11 @@ import type { TuonoConfig } from 'tuono/config' +import { path } from 'tuono/config' const config: TuonoConfig = { vite: { - alias: { 'my-alias': 'my-alias' }, + alias: { + '@': path.join(__dirname, './src'), + }, }, } diff --git a/examples/tuono-tutorial/tsconfig.json b/examples/tuono-tutorial/tsconfig.json index 8d08b177..e7ce4768 100644 --- a/examples/tuono-tutorial/tsconfig.json +++ b/examples/tuono-tutorial/tsconfig.json @@ -18,7 +18,10 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "paths": { + "@/*": ["./src/*"] + } }, "include": ["src", "tuono.config.ts"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/examples/tuono-tutorial/tuono.config.ts b/examples/tuono-tutorial/tuono.config.ts index 8073f648..bc440a23 100644 --- a/examples/tuono-tutorial/tuono.config.ts +++ b/examples/tuono-tutorial/tuono.config.ts @@ -1,8 +1,11 @@ import type { TuonoConfig } from 'tuono/config' +import { path } from 'tuono/config' const config: TuonoConfig = { vite: { - alias: { 'my-alias': 'my-alias' }, + alias: { + '@': path.join(__dirname, './src'), + }, }, } diff --git a/examples/with-mdx/tsconfig.json b/examples/with-mdx/tsconfig.json index 8d08b177..e7ce4768 100644 --- a/examples/with-mdx/tsconfig.json +++ b/examples/with-mdx/tsconfig.json @@ -18,7 +18,10 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "paths": { + "@/*": ["./src/*"] + } }, "include": ["src", "tuono.config.ts"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/examples/with-mdx/tuono.config.ts b/examples/with-mdx/tuono.config.ts index 8073f648..bc440a23 100644 --- a/examples/with-mdx/tuono.config.ts +++ b/examples/with-mdx/tuono.config.ts @@ -1,8 +1,11 @@ import type { TuonoConfig } from 'tuono/config' +import { path } from 'tuono/config' const config: TuonoConfig = { vite: { - alias: { 'my-alias': 'my-alias' }, + alias: { + '@': path.join(__dirname, './src'), + }, }, } From 940eb6315f3bd8576937cf5b6fcd2228ef936615 Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Thu, 28 Nov 2024 19:23:03 +0100 Subject: [PATCH 10/20] chore: update examples paths --- examples/tuono-tutorial/src/routes/index.tsx | 2 +- examples/tuono-tutorial/src/routes/pokemons/[pokemon].tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/tuono-tutorial/src/routes/index.tsx b/examples/tuono-tutorial/src/routes/index.tsx index 5700f0ee..dc08aced 100644 --- a/examples/tuono-tutorial/src/routes/index.tsx +++ b/examples/tuono-tutorial/src/routes/index.tsx @@ -2,7 +2,7 @@ import type { JSX } from 'react' import { Head, type TuonoProps } from 'tuono' -import PokemonLink from '../components/PokemonLink' +import PokemonLink from '@/components/PokemonLink' interface Pokemon { name: string diff --git a/examples/tuono-tutorial/src/routes/pokemons/[pokemon].tsx b/examples/tuono-tutorial/src/routes/pokemons/[pokemon].tsx index 251f1efe..cfb2ea72 100644 --- a/examples/tuono-tutorial/src/routes/pokemons/[pokemon].tsx +++ b/examples/tuono-tutorial/src/routes/pokemons/[pokemon].tsx @@ -1,7 +1,7 @@ import type { JSX } from 'react' import { Head, type TuonoProps } from 'tuono' -import PokemonView from '../../components/PokemonView' +import PokemonView from '@/components/PokemonView' interface Pokemon { name: string From ff5553e2bf4a9794a4a696d1a36418ebfcd5544c Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Fri, 29 Nov 2024 21:06:25 +0100 Subject: [PATCH 11/20] feat: sanitize config aliases --- examples/tuono-tutorial/tuono.config.ts | 3 +- packages/tuono/src/build/index.ts | 5 +- packages/tuono/src/build/utils.ts | 65 +++++++++++++++++++++++-- packages/tuono/src/config/index.ts | 3 -- packages/tuono/src/config/path.ts | 10 ---- 5 files changed, 64 insertions(+), 22 deletions(-) delete mode 100644 packages/tuono/src/config/path.ts diff --git a/examples/tuono-tutorial/tuono.config.ts b/examples/tuono-tutorial/tuono.config.ts index bc440a23..cd34c2c6 100644 --- a/examples/tuono-tutorial/tuono.config.ts +++ b/examples/tuono-tutorial/tuono.config.ts @@ -1,10 +1,9 @@ import type { TuonoConfig } from 'tuono/config' -import { path } from 'tuono/config' const config: TuonoConfig = { vite: { alias: { - '@': path.join(__dirname, './src'), + '@': 'src', }, }, } diff --git a/packages/tuono/src/build/index.ts b/packages/tuono/src/build/index.ts index f622ddd6..5458a9ea 100644 --- a/packages/tuono/src/build/index.ts +++ b/packages/tuono/src/build/index.ts @@ -88,6 +88,7 @@ const developmentCSRWatch = () => { const buildProd = () => { blockingAsync(async () => { const config = await loadConfig() + await build( mergeConfig(BASE_CONFIG, { resolve: { @@ -145,9 +146,7 @@ const buildConfig = () => { rollupOptions: { input: './tuono.config.ts', output: { - entryFileNames: 'config.js', - name: 'config', - format: 'cjs', + entryFileNames: 'config.mjs', }, }, }, diff --git a/packages/tuono/src/build/utils.ts b/packages/tuono/src/build/utils.ts index 3471ff5b..7ee93d6d 100644 --- a/packages/tuono/src/build/utils.ts +++ b/packages/tuono/src/build/utils.ts @@ -1,11 +1,68 @@ -import { TuonoConfig } from '../config' +import type { AliasOptions } from 'vite' +import type { TuonoConfig } from '../config' +import path from 'path' + +const DOT_TUONO = '.tuono' +const CONFIG_FOLDER = 'config' +const CONFIG_FILE = 'config.mjs' + +/** + * Sanitize the vite alias: + * - If the path is a relative path transfrorm it to absolute applying the tuono root folder + * - If the path is absolute remove the ".tuono/config/" path from it + */ +const cleanAliasPath = (filePath: string): string => { + if (path.isAbsolute(filePath)) { + return filePath.replace(path.join(DOT_TUONO, CONFIG_FOLDER), '') + } else { + return path.join(process.cwd(), filePath) + } +} + +/** + * Iterator over the config.vite.alias entry + */ +const sanitizeViteAlias = (alias?: AliasOptions): AliasOptions | undefined => { + if (!alias) return + + if (Array.isArray(alias)) { + return alias.map(({ find, replacement }) => ({ + find, + replacement: cleanAliasPath(replacement), + })) + } + if (typeof alias === 'object') { + let object: AliasOptions = {} + for (let [key, value] of Object.entries(alias)) { + object[key] = cleanAliasPath(value) + } + return object + } + + return alias +} + +/** + * Wrapper function to sanitize the tuono.config.ts file + */ +const sanitizeConfig = (config: TuonoConfig): TuonoConfig => { + return { + ...config, + vite: { + alias: sanitizeViteAlias(config?.vite?.alias), + }, + } +} export const loadConfig = async (): Promise => { try { - const configFile = await import(`${process.cwd()}/.tuono/config/config.js`) - return configFile.default - } catch { + const configFile = await import( + path.join(process.cwd(), DOT_TUONO, CONFIG_FOLDER, CONFIG_FILE) + ) + return sanitizeConfig(configFile.default) + } catch (err) { console.error('Failed to load tuono.config.ts') + console.error(err) return {} } } diff --git a/packages/tuono/src/config/index.ts b/packages/tuono/src/config/index.ts index a4012d94..b7c6b20d 100644 --- a/packages/tuono/src/config/index.ts +++ b/packages/tuono/src/config/index.ts @@ -1,4 +1 @@ export type { TuonoConfig } from './types' -import path from './path' - -export { path } diff --git a/packages/tuono/src/config/path.ts b/packages/tuono/src/config/path.ts deleted file mode 100644 index ea50df7e..00000000 --- a/packages/tuono/src/config/path.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Return the string cleared by the config path - */ -const join = (base: string, folder: string): string => { - return base.replace('.tuono/config', '').concat(folder.replace('./', '')) -} - -export default { - join, -} From 813169f49d4acec696d7ab77f3f666df4f398ff0 Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Fri, 29 Nov 2024 21:08:13 +0100 Subject: [PATCH 12/20] chore: remove config from examples --- examples/tuono-app/tuono.config.ts | 9 +-------- examples/with-mdx/tuono.config.ts | 9 +-------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/examples/tuono-app/tuono.config.ts b/examples/tuono-app/tuono.config.ts index bc440a23..a70b2924 100644 --- a/examples/tuono-app/tuono.config.ts +++ b/examples/tuono-app/tuono.config.ts @@ -1,12 +1,5 @@ import type { TuonoConfig } from 'tuono/config' -import { path } from 'tuono/config' -const config: TuonoConfig = { - vite: { - alias: { - '@': path.join(__dirname, './src'), - }, - }, -} +const config: TuonoConfig = {} export default config diff --git a/examples/with-mdx/tuono.config.ts b/examples/with-mdx/tuono.config.ts index bc440a23..a70b2924 100644 --- a/examples/with-mdx/tuono.config.ts +++ b/examples/with-mdx/tuono.config.ts @@ -1,12 +1,5 @@ import type { TuonoConfig } from 'tuono/config' -import { path } from 'tuono/config' -const config: TuonoConfig = { - vite: { - alias: { - '@': path.join(__dirname, './src'), - }, - }, -} +const config: TuonoConfig = {} export default config From 8325590b015bf7642db13ebf69c7025545f15585 Mon Sep 17 00:00:00 2001 From: Marco Pasqualetti Date: Sat, 30 Nov 2024 12:17:21 +0100 Subject: [PATCH 13/20] refactor(packages/tuono): refine config normalize --- packages/tuono/src/build/constants.ts | 3 ++ packages/tuono/src/build/utils.ts | 62 +++++++++++++++++---------- 2 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 packages/tuono/src/build/constants.ts diff --git a/packages/tuono/src/build/constants.ts b/packages/tuono/src/build/constants.ts new file mode 100644 index 00000000..b82bc74f --- /dev/null +++ b/packages/tuono/src/build/constants.ts @@ -0,0 +1,3 @@ +export const DOT_TUONO_FOLDER_NAME = '.tuono' +export const CONFIG_FOLDER_NAME = 'config' +export const CONFIG_FILE_NAME = 'config.mjs' diff --git a/packages/tuono/src/build/utils.ts b/packages/tuono/src/build/utils.ts index 7ee93d6d..3e3f27d9 100644 --- a/packages/tuono/src/build/utils.ts +++ b/packages/tuono/src/build/utils.ts @@ -1,55 +1,68 @@ +import path from 'path' + import type { AliasOptions } from 'vite' + import type { TuonoConfig } from '../config' -import path from 'path' -const DOT_TUONO = '.tuono' -const CONFIG_FOLDER = 'config' -const CONFIG_FILE = 'config.mjs' +import { + DOT_TUONO_FOLDER_NAME, + CONFIG_FOLDER_NAME, + CONFIG_FILE_NAME, +} from './constants' /** - * Sanitize the vite alias: - * - If the path is a relative path transfrorm it to absolute applying the tuono root folder - * - If the path is absolute remove the ".tuono/config/" path from it + * Normalize vite alias option: + * - If the path is relative, transform it to absolute, prepending the tuono root folder + * - If the path is absolute, remove the ".tuono/config/" path from it */ -const cleanAliasPath = (filePath: string): string => { +const normalizeAliasPath = (filePath: string): string => { if (path.isAbsolute(filePath)) { - return filePath.replace(path.join(DOT_TUONO, CONFIG_FOLDER), '') - } else { - return path.join(process.cwd(), filePath) + return filePath.replace( + path.join(DOT_TUONO_FOLDER_NAME, CONFIG_FOLDER_NAME), + '', + ) } + + return path.join(process.cwd(), filePath) } /** - * Iterator over the config.vite.alias entry + * From a given vite aliasOptions apply {@link normalizeAliasPath} for each alias. + * + * The config is bundled by `vite` and emitted inside {@link DOT_TUONO_FOLDER_NAME}/{@link CONFIG_FOLDER_NAME}. + * According to this, we have to ensure that the aliases provided by the user are updated to refer to the right folders. + * + * @see https://github.com/Valerioageno/tuono/pull/153#issuecomment-2508142877 */ -const sanitizeViteAlias = (alias?: AliasOptions): AliasOptions | undefined => { +const normalizeViteAlias = (alias?: AliasOptions): AliasOptions | undefined => { if (!alias) return if (Array.isArray(alias)) { return alias.map(({ find, replacement }) => ({ find, - replacement: cleanAliasPath(replacement), + replacement: normalizeAliasPath(replacement), })) } + if (typeof alias === 'object') { - let object: AliasOptions = {} + let normalizedAlias: AliasOptions = {} for (let [key, value] of Object.entries(alias)) { - object[key] = cleanAliasPath(value) + normalizedAlias[key] = normalizeAliasPath(value) } - return object + return normalizedAlias } return alias } /** - * Wrapper function to sanitize the tuono.config.ts file + * Wrapper function to normalize the tuono.config.ts file */ -const sanitizeConfig = (config: TuonoConfig): TuonoConfig => { +const normalizeConfig = (config: TuonoConfig): TuonoConfig => { return { ...config, vite: { - alias: sanitizeViteAlias(config?.vite?.alias), + alias: normalizeViteAlias(config?.vite?.alias), }, } } @@ -57,9 +70,14 @@ const sanitizeConfig = (config: TuonoConfig): TuonoConfig => { export const loadConfig = async (): Promise => { try { const configFile = await import( - path.join(process.cwd(), DOT_TUONO, CONFIG_FOLDER, CONFIG_FILE) + path.join( + process.cwd(), + DOT_TUONO_FOLDER_NAME, + CONFIG_FOLDER_NAME, + CONFIG_FILE_NAME, + ) ) - return sanitizeConfig(configFile.default) + return normalizeConfig(configFile.default) } catch (err) { console.error('Failed to load tuono.config.ts') console.error(err) From ff9959a3fe7512edf5cd940492286a83ab753582 Mon Sep 17 00:00:00 2001 From: Marco Pasqualetti Date: Sat, 30 Nov 2024 14:59:00 +0100 Subject: [PATCH 14/20] fix(packages/tuono): handle library in `normalizeAliasPath` --- packages/tuono/src/build/utils.ts | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/packages/tuono/src/build/utils.ts b/packages/tuono/src/build/utils.ts index 3e3f27d9..83995db4 100644 --- a/packages/tuono/src/build/utils.ts +++ b/packages/tuono/src/build/utils.ts @@ -12,18 +12,23 @@ import { /** * Normalize vite alias option: - * - If the path is relative, transform it to absolute, prepending the tuono root folder + * - If the path starts with `src` folder, transform it to absolute, prepending the tuono root folder * - If the path is absolute, remove the ".tuono/config/" path from it + * - Otherwise leave the path untouched */ -const normalizeAliasPath = (filePath: string): string => { - if (path.isAbsolute(filePath)) { - return filePath.replace( +const normalizeAliasPath = (aliasPath: string): string => { + if (aliasPath.startsWith('./src') || aliasPath.startsWith('src')) { + return path.join(process.cwd(), aliasPath) + } + + if (path.isAbsolute(aliasPath)) { + return aliasPath.replace( path.join(DOT_TUONO_FOLDER_NAME, CONFIG_FOLDER_NAME), '', ) } - return path.join(process.cwd(), filePath) + return aliasPath } /** @@ -38,8 +43,8 @@ const normalizeViteAlias = (alias?: AliasOptions): AliasOptions | undefined => { if (!alias) return if (Array.isArray(alias)) { - return alias.map(({ find, replacement }) => ({ - find, + return alias.map(({ replacement, ...userAliasDefinition }) => ({ + ...userAliasDefinition, replacement: normalizeAliasPath(replacement), })) } @@ -57,10 +62,13 @@ const normalizeViteAlias = (alias?: AliasOptions): AliasOptions | undefined => { /** * Wrapper function to normalize the tuono.config.ts file + * + * @warning Exported for unit test. + * There is no easy way to mock the module export and change it in every test + * and also testing the error */ -const normalizeConfig = (config: TuonoConfig): TuonoConfig => { +export const normalizeConfig = (config: TuonoConfig): TuonoConfig => { return { - ...config, vite: { alias: normalizeViteAlias(config?.vite?.alias), }, @@ -77,6 +85,7 @@ export const loadConfig = async (): Promise => { CONFIG_FILE_NAME, ) ) + return normalizeConfig(configFile.default) } catch (err) { console.error('Failed to load tuono.config.ts') From a020fb6293a6c52ad890ffcaf8684a18a00096e8 Mon Sep 17 00:00:00 2001 From: Marco Pasqualetti Date: Sat, 30 Nov 2024 15:29:12 +0100 Subject: [PATCH 15/20] test(packages/tuono): add config normalize tests --- packages/tuono/package.json | 4 +- packages/tuono/src/build/utils.spec.ts | 118 +++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 packages/tuono/src/build/utils.spec.ts diff --git a/packages/tuono/package.json b/packages/tuono/package.json index f3027dba..0c118910 100644 --- a/packages/tuono/package.json +++ b/packages/tuono/package.json @@ -9,7 +9,9 @@ "lint": "eslint --ext .ts,.tsx ./src -c ../../.eslintrc", "format": "prettier -u --write --ignore-unknown '**/*'", "format:check": "prettier --check --ignore-unknown '**/*'", - "types": "tsc --noEmit" + "types": "tsc --noEmit", + "test:watch": "vitest", + "test": "vitest run" }, "type": "module", "types": "dist/esm/index.d.ts", diff --git a/packages/tuono/src/build/utils.spec.ts b/packages/tuono/src/build/utils.spec.ts new file mode 100644 index 00000000..74d73d73 --- /dev/null +++ b/packages/tuono/src/build/utils.spec.ts @@ -0,0 +1,118 @@ +import { describe, expect, it, vi } from 'vitest' + +import type { TuonoConfig } from '../config' + +import { loadConfig, normalizeConfig } from './utils' + +const PROCESS_CWD_MOCK = 'PROCESS_CWD_MOCK' + +vi.spyOn(process, 'cwd').mockReturnValue(PROCESS_CWD_MOCK) + +describe('loadConfig', () => { + it('should error if the config does not exist', async () => { + const consoleErrorSpy = vi + .spyOn(console, 'error') + .mockImplementation(() => {}) + await loadConfig() + + expect(consoleErrorSpy).toHaveBeenCalledTimes(2) + }) +}) + +describe('normalizeConfig - vite - alias', () => { + it('should return the config as is, adding `vite` with alias', () => { + const config: TuonoConfig = {} + expect(normalizeConfig(config)).toStrictEqual({ + vite: { alias: undefined }, + }) + }) + + it('should return an empty config if invalid values are provided', () => { + // @ts-expect-error testing invalid config + expect(normalizeConfig({ invalid: true })).toStrictEqual({ + vite: { alias: undefined }, + }) + }) + + it('should not modify alias pointing to packages', () => { + const libraryName = '@tabler/icons-react' + const libraryAlias = '@tabler/icons-react/dist/esm/icons/index.mjs' + const config: TuonoConfig = { + vite: { alias: { [libraryName]: libraryAlias } }, + } + expect(normalizeConfig(config)).toMatchInlineSnapshot(` + { + "vite": { + "alias": { + "@tabler/icons-react": "@tabler/icons-react/dist/esm/icons/index.mjs", + }, + }, + } + `) + }) + + it('should transform relative paths to absolute path relative to process.cwd()', () => { + const config: TuonoConfig = { + vite: { alias: { '@': './src', '@no-prefix': 'src' } }, + } + + expect(normalizeConfig(config)).toMatchInlineSnapshot(` + { + "vite": { + "alias": { + "@": "PROCESS_CWD_MOCK/src", + "@no-prefix": "PROCESS_CWD_MOCK/src", + }, + }, + } + `) + }) + + it('should not transform alias with absolute path', () => { + const config: TuonoConfig = { + vite: { alias: { '@1': '/src/pippo', '@2': 'file://pluto' } }, + } + expect(normalizeConfig(config)).toMatchInlineSnapshot(` + { + "vite": { + "alias": { + "@1": "/src/pippo", + "@2": "file://pluto", + }, + }, + } + `) + }) + + it('should apply previuos behaviuor when using alias as list', () => { + const config: TuonoConfig = { + vite: { + alias: [ + { find: '1', replacement: '@tabler/icons-react-fun' }, + { find: '2', replacement: './src' }, + { find: '3', replacement: 'file://pluto' }, + ], + }, + } + expect(normalizeConfig(config)).toMatchInlineSnapshot(` + { + "vite": { + "alias": [ + { + "find": "1", + "replacement": "@tabler/icons-react-fun", + }, + { + "find": "2", + "replacement": "PROCESS_CWD_MOCK/src", + }, + { + "find": "3", + "replacement": "file://pluto", + }, + ], + }, + } + `) + }) +}) From 576cd4d318d14ffb301e9f4dc8ae8a630c01d707 Mon Sep 17 00:00:00 2001 From: Marco Pasqualetti Date: Sat, 30 Nov 2024 15:36:55 +0100 Subject: [PATCH 16/20] test(packages/tuono): correct test for windows --- packages/tuono/src/build/utils.spec.ts | 86 ++++++++++++-------------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/packages/tuono/src/build/utils.spec.ts b/packages/tuono/src/build/utils.spec.ts index 74d73d73..a327f769 100644 --- a/packages/tuono/src/build/utils.spec.ts +++ b/packages/tuono/src/build/utils.spec.ts @@ -1,3 +1,5 @@ +import path from 'node:path' + import { describe, expect, it, vi } from 'vitest' import type { TuonoConfig } from '../config' @@ -40,15 +42,13 @@ describe('normalizeConfig - vite - alias', () => { const config: TuonoConfig = { vite: { alias: { [libraryName]: libraryAlias } }, } - expect(normalizeConfig(config)).toMatchInlineSnapshot(` - { - "vite": { - "alias": { - "@tabler/icons-react": "@tabler/icons-react/dist/esm/icons/index.mjs", - }, + expect(normalizeConfig(config)).toStrictEqual({ + vite: { + alias: { + '@tabler/icons-react': '@tabler/icons-react/dist/esm/icons/index.mjs', }, - } - `) + }, + }) }) it('should transform relative paths to absolute path relative to process.cwd()', () => { @@ -56,32 +56,28 @@ describe('normalizeConfig - vite - alias', () => { vite: { alias: { '@': './src', '@no-prefix': 'src' } }, } - expect(normalizeConfig(config)).toMatchInlineSnapshot(` - { - "vite": { - "alias": { - "@": "PROCESS_CWD_MOCK/src", - "@no-prefix": "PROCESS_CWD_MOCK/src", - }, + expect(normalizeConfig(config)).toStrictEqual({ + vite: { + alias: { + '@': path.join(PROCESS_CWD_MOCK, 'src'), + '@no-prefix': path.join(PROCESS_CWD_MOCK, 'src'), }, - } - `) + }, + }) }) it('should not transform alias with absolute path', () => { const config: TuonoConfig = { vite: { alias: { '@1': '/src/pippo', '@2': 'file://pluto' } }, } - expect(normalizeConfig(config)).toMatchInlineSnapshot(` - { - "vite": { - "alias": { - "@1": "/src/pippo", - "@2": "file://pluto", - }, + expect(normalizeConfig(config)).toStrictEqual({ + vite: { + alias: { + '@1': '/src/pippo', + '@2': 'file://pluto', }, - } - `) + }, + }) }) it('should apply previuos behaviuor when using alias as list', () => { @@ -94,25 +90,23 @@ describe('normalizeConfig - vite - alias', () => { ], }, } - expect(normalizeConfig(config)).toMatchInlineSnapshot(` - { - "vite": { - "alias": [ - { - "find": "1", - "replacement": "@tabler/icons-react-fun", - }, - { - "find": "2", - "replacement": "PROCESS_CWD_MOCK/src", - }, - { - "find": "3", - "replacement": "file://pluto", - }, - ], - }, - } - `) + expect(normalizeConfig(config)).toStrictEqual({ + vite: { + alias: [ + { + find: '1', + replacement: '@tabler/icons-react-fun', + }, + { + find: '2', + replacement: path.join(PROCESS_CWD_MOCK, 'src'), + }, + { + find: '3', + replacement: 'file://pluto', + }, + ], + }, + }) }) }) From 69f19e5afe7a6d3a97629e9febd0a1c1254522dc Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Sat, 30 Nov 2024 17:38:56 +0100 Subject: [PATCH 17/20] chore: remove paths typescript field --- examples/tuono-app/tsconfig.json | 5 +---- examples/with-mdx/tsconfig.json | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/examples/tuono-app/tsconfig.json b/examples/tuono-app/tsconfig.json index e7ce4768..8d08b177 100644 --- a/examples/tuono-app/tsconfig.json +++ b/examples/tuono-app/tsconfig.json @@ -18,10 +18,7 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "paths": { - "@/*": ["./src/*"] - } + "noFallthroughCasesInSwitch": true }, "include": ["src", "tuono.config.ts"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/examples/with-mdx/tsconfig.json b/examples/with-mdx/tsconfig.json index e7ce4768..8d08b177 100644 --- a/examples/with-mdx/tsconfig.json +++ b/examples/with-mdx/tsconfig.json @@ -18,10 +18,7 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "paths": { - "@/*": ["./src/*"] - } + "noFallthroughCasesInSwitch": true }, "include": ["src", "tuono.config.ts"], "references": [{ "path": "./tsconfig.node.json" }] From 7a0b32791b67fd3a2140812c6432854009e98998 Mon Sep 17 00:00:00 2001 From: Valerio Ageno <51341197+Valerioageno@users.noreply.github.com> Date: Sat, 30 Nov 2024 18:28:24 +0100 Subject: [PATCH 18/20] fix: update windows config bin file path --- crates/tuono/src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/tuono/src/app.rs b/crates/tuono/src/app.rs index f41922fd..5d428623 100644 --- a/crates/tuono/src/app.rs +++ b/crates/tuono/src/app.rs @@ -22,7 +22,7 @@ const ROUTES_FOLDER_PATH: &str = "\\src\\routes"; const BUILD_JS_SCRIPT: &str = ".\\node_modules\\.bin\\tuono-build-prod.cmd"; #[cfg(target_os = "windows")] -const BUILD_TUONO_CONFIG: &str = ".\\node_modules\\.bin\\tuono-build-prod.cmd"; +const BUILD_TUONO_CONFIG: &str = ".\\node_modules\\.bin\\tuono-build-config.cmd"; #[cfg(not(target_os = "windows"))] const ROUTES_FOLDER_PATH: &str = "/src/routes"; From ded75bb411bf05237913b1e7b62316d35f0f907a Mon Sep 17 00:00:00 2001 From: Valerio Ageno <51341197+Valerioageno@users.noreply.github.com> Date: Sat, 30 Nov 2024 18:28:41 +0100 Subject: [PATCH 19/20] fix: allow windows to load absolute config file --- packages/tuono/src/build/utils.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/tuono/src/build/utils.ts b/packages/tuono/src/build/utils.ts index 83995db4..c11a7cd1 100644 --- a/packages/tuono/src/build/utils.ts +++ b/packages/tuono/src/build/utils.ts @@ -9,6 +9,7 @@ import { CONFIG_FOLDER_NAME, CONFIG_FILE_NAME, } from './constants' +import { pathToFileURL } from 'url' /** * Normalize vite alias option: @@ -78,12 +79,12 @@ export const normalizeConfig = (config: TuonoConfig): TuonoConfig => { export const loadConfig = async (): Promise => { try { const configFile = await import( - path.join( + pathToFileURL(path.join( process.cwd(), DOT_TUONO_FOLDER_NAME, CONFIG_FOLDER_NAME, CONFIG_FILE_NAME, - ) + )).href ) return normalizeConfig(configFile.default) From f84ffcbfec116d5822353e4774960d9399153f1e Mon Sep 17 00:00:00 2001 From: Valerio Ageno Date: Sat, 30 Nov 2024 18:31:49 +0100 Subject: [PATCH 20/20] fix: formatting --- packages/tuono/src/build/utils.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/tuono/src/build/utils.ts b/packages/tuono/src/build/utils.ts index c11a7cd1..89aa7639 100644 --- a/packages/tuono/src/build/utils.ts +++ b/packages/tuono/src/build/utils.ts @@ -79,12 +79,14 @@ export const normalizeConfig = (config: TuonoConfig): TuonoConfig => { export const loadConfig = async (): Promise => { try { const configFile = await import( - pathToFileURL(path.join( - process.cwd(), - DOT_TUONO_FOLDER_NAME, - CONFIG_FOLDER_NAME, - CONFIG_FILE_NAME, - )).href + pathToFileURL( + path.join( + process.cwd(), + DOT_TUONO_FOLDER_NAME, + CONFIG_FOLDER_NAME, + CONFIG_FILE_NAME, + ), + ).href ) return normalizeConfig(configFile.default)