@blinkk/root 2.0.0-rc.0 → 2.0.0

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.
@@ -1,14 +1,13 @@
1
1
  import {
2
2
  getVitePlugins
3
- } from "./chunk-ZUUGSC6Z.js";
3
+ } from "./chunk-MA6MSEP4.js";
4
4
 
5
- // src/node/load-config.ts
5
+ // src/node/monorepo.ts
6
6
  import path2 from "node:path";
7
- import { bundleRequire } from "bundle-require";
8
- import { build } from "esbuild";
7
+ import { getWorkspaces, getWorkspaceRoot } from "workspace-tools";
9
8
 
10
9
  // src/utils/fsutils.ts
11
- import { promises as fs } from "node:fs";
10
+ import fs from "node:fs";
12
11
  import path from "node:path";
13
12
  import fsExtra from "fs-extra";
14
13
  import glob from "tiny-glob";
@@ -18,13 +17,13 @@ function isJsFile(filename) {
18
17
  async function writeFile(filepath, content) {
19
18
  const dirPath = path.dirname(filepath);
20
19
  await makeDir(dirPath);
21
- await fs.writeFile(filepath, content);
20
+ await fs.promises.writeFile(filepath, content);
22
21
  }
23
22
  async function makeDir(dirpath) {
24
23
  try {
25
- await fs.access(dirpath);
24
+ await fs.promises.access(dirpath);
26
25
  } catch (e) {
27
- await fs.mkdir(dirpath, { recursive: true });
26
+ await fs.promises.mkdir(dirpath, { recursive: true });
28
27
  }
29
28
  }
30
29
  async function copyDir(srcdir, dstdir) {
@@ -43,10 +42,14 @@ async function copyGlob(pattern, srcdir, dstdir) {
43
42
  });
44
43
  }
45
44
  async function rmDir(dirpath) {
46
- await fs.rm(dirpath, { recursive: true, force: true });
45
+ await fs.promises.rm(dirpath, { recursive: true, force: true });
47
46
  }
48
47
  async function loadJson(filepath) {
49
- const content = await fs.readFile(filepath, "utf-8");
48
+ const content = await fs.promises.readFile(filepath, "utf-8");
49
+ return JSON.parse(content);
50
+ }
51
+ function loadJsonSync(filepath) {
52
+ const content = fs.readFileSync(filepath, "utf-8");
50
53
  return JSON.parse(content);
51
54
  }
52
55
  async function writeJson(filepath, data) {
@@ -54,7 +57,7 @@ async function writeJson(filepath, data) {
54
57
  await writeFile(filepath, content);
55
58
  }
56
59
  async function isDirectory(dirpath) {
57
- return fs.stat(dirpath).then((fsStat) => {
60
+ return fs.promises.stat(dirpath).then((fsStat) => {
58
61
  return fsStat.isDirectory();
59
62
  }).catch((err) => {
60
63
  if (err.code === "ENOENT") {
@@ -64,11 +67,19 @@ async function isDirectory(dirpath) {
64
67
  });
65
68
  }
66
69
  function fileExists(filepath) {
67
- return fs.access(filepath).then(() => true).catch(() => false);
70
+ return fs.promises.access(filepath).then(() => true).catch(() => false);
71
+ }
72
+ function fileExistsSync(filepath) {
73
+ try {
74
+ fs.accessSync(filepath);
75
+ return true;
76
+ } catch {
77
+ return false;
78
+ }
68
79
  }
69
80
  async function dirExists(dirpath) {
70
81
  try {
71
- const stat = await fs.stat(dirpath);
82
+ const stat = await fs.promises.stat(dirpath);
72
83
  return stat.isDirectory();
73
84
  } catch (error) {
74
85
  if (error.code === "ENOENT") {
@@ -78,21 +89,105 @@ async function dirExists(dirpath) {
78
89
  }
79
90
  }
80
91
  async function directoryContains(dirpath, subpath) {
81
- const outer = await fs.realpath(dirpath);
82
- const inner = await fs.realpath(subpath);
92
+ const outer = await fs.promises.realpath(dirpath);
93
+ const inner = await fs.promises.realpath(subpath);
83
94
  const rel = path.relative(outer, inner);
84
95
  return !rel.startsWith("..");
85
96
  }
86
97
 
98
+ // src/node/monorepo.ts
99
+ function loadPackageJson(filepath) {
100
+ if (!fileExistsSync(filepath)) {
101
+ return null;
102
+ }
103
+ return loadJsonSync(filepath);
104
+ }
105
+ function getMonorepoPackages(rootDir) {
106
+ const monorepoRoot = getWorkspaceRoot(rootDir);
107
+ if (!monorepoRoot) {
108
+ return {};
109
+ }
110
+ const workspaces = getWorkspaces(monorepoRoot);
111
+ const packages = {};
112
+ workspaces.forEach((workspaceInfo) => {
113
+ packages[workspaceInfo.name] = workspaceInfo;
114
+ });
115
+ return packages;
116
+ }
117
+ function getMonorepoPackageDeps(rootDir) {
118
+ const monorepoRoot = getWorkspaceRoot(rootDir);
119
+ if (!monorepoRoot) {
120
+ return {};
121
+ }
122
+ const packageJsonPath = path2.join(monorepoRoot, "package.json");
123
+ const packageJson = loadPackageJson(packageJsonPath);
124
+ return packageJson?.dependencies || {};
125
+ }
126
+ function flattenPackageDepsFromMonorepo(rootDir, options) {
127
+ const packageJsonPath = path2.resolve(rootDir, "package.json");
128
+ const packageJson = loadPackageJson(packageJsonPath);
129
+ const monorepoDeps = getMonorepoPackageDeps(rootDir);
130
+ const projectDeps = {
131
+ ...packageJson?.peerDependencies,
132
+ ...packageJson?.dependencies
133
+ };
134
+ const allDeps = {};
135
+ const workspacePackages = getMonorepoPackages(rootDir);
136
+ const ignore = options?.ignore || /* @__PURE__ */ new Set();
137
+ Object.entries(projectDeps).forEach(([depName, depVersion]) => {
138
+ if (depName.startsWith("@blinkk/root") && depVersion.startsWith("workspace:")) {
139
+ const packageInfo = workspacePackages[depName];
140
+ if (packageInfo) {
141
+ allDeps[depName] = packageInfo.packageJson.version;
142
+ }
143
+ } else if (depVersion.startsWith("workspace:")) {
144
+ if (ignore.has(depName)) {
145
+ return;
146
+ }
147
+ ignore.add(depName);
148
+ const packageInfo = workspacePackages[depName];
149
+ if (packageInfo) {
150
+ const workspacePackageDir = packageInfo.path;
151
+ const deps = flattenPackageDepsFromMonorepo(workspacePackageDir, {
152
+ ignore
153
+ });
154
+ for (const key in deps) {
155
+ const currentValue = allDeps[key];
156
+ if (deps[key] && deps[key] !== "*" && (!currentValue || currentValue === "*")) {
157
+ allDeps[key] = deps[key];
158
+ }
159
+ }
160
+ }
161
+ } else if (depVersion === "*" && monorepoDeps[depName]) {
162
+ allDeps[depName] = monorepoDeps[depName];
163
+ } else {
164
+ allDeps[depName] = depVersion;
165
+ }
166
+ });
167
+ return sortDeps(allDeps);
168
+ }
169
+ function sortDeps(deps) {
170
+ const keys = Object.keys(deps).sort();
171
+ const sortedDeps = {};
172
+ for (const key of keys) {
173
+ sortedDeps[key] = deps[key];
174
+ }
175
+ return sortedDeps;
176
+ }
177
+
87
178
  // src/node/load-config.ts
179
+ import path3 from "node:path";
180
+ import { bundleRequire } from "bundle-require";
181
+ import { build } from "esbuild";
88
182
  async function loadRootConfig(rootDir, options) {
89
- const configPath = path2.resolve(rootDir, "root.config.ts");
183
+ const configPath = path3.resolve(rootDir, "root.config.ts");
90
184
  const exists = await fileExists(configPath);
91
185
  if (!exists) {
92
186
  throw new Error(`${configPath} does not exist`);
93
187
  }
94
188
  const configBundle = await bundleRequire({
95
- filepath: configPath
189
+ filepath: configPath,
190
+ esbuildOptions: { plugins: [esbuildExternalsPlugin({ rootDir })] }
96
191
  });
97
192
  let config = configBundle.mod.default || {};
98
193
  if (typeof config === "function") {
@@ -101,27 +196,11 @@ async function loadRootConfig(rootDir, options) {
101
196
  return Object.assign({}, config, { rootDir });
102
197
  }
103
198
  async function bundleRootConfig(rootDir, outPath) {
104
- const configPath = path2.resolve(rootDir, "root.config.ts");
199
+ const configPath = path3.resolve(rootDir, "root.config.ts");
105
200
  const configExists = await fileExists(configPath);
106
201
  if (!configExists) {
107
202
  throw new Error(`${configPath} does not exist`);
108
203
  }
109
- const packageJsonPath = path2.resolve(rootDir, "package.json");
110
- const packageJson = await loadPackageJson(packageJsonPath);
111
- const allDeps = {
112
- ...packageJson.peerDependencies,
113
- ...packageJson.dependencies
114
- };
115
- function getPackageName(id) {
116
- const segments = id.split("/");
117
- if (segments.length > 1) {
118
- if (segments[0].startsWith("@") && segments[0].length > 1) {
119
- return `${segments[0]}/${segments[1]}`;
120
- }
121
- return segments[0];
122
- }
123
- return id;
124
- }
125
204
  await build({
126
205
  entryPoints: [configPath],
127
206
  bundle: true,
@@ -131,30 +210,11 @@ async function bundleRootConfig(rootDir, outPath) {
131
210
  sourcemap: "inline",
132
211
  metafile: true,
133
212
  format: "esm",
134
- plugins: [
135
- // Externalizes deps that are in package.json.
136
- {
137
- name: "externalize-package-json-deps",
138
- setup(build2) {
139
- build2.onResolve({ filter: /.*/ }, (args) => {
140
- const id = args.path;
141
- if (id[0] !== "." && !id.startsWith("@/")) {
142
- const packageName = getPackageName(id);
143
- if (packageName in allDeps) {
144
- return {
145
- external: true
146
- };
147
- }
148
- }
149
- return null;
150
- });
151
- }
152
- }
153
- ]
213
+ plugins: [esbuildExternalsPlugin({ rootDir })]
154
214
  });
155
215
  }
156
216
  async function loadBundledConfig(rootDir, options) {
157
- const configPath = path2.resolve(rootDir, "dist/root.config.js");
217
+ const configPath = path3.resolve(rootDir, "dist/root.config.js");
158
218
  const exists = await fileExists(configPath);
159
219
  if (!exists) {
160
220
  throw new Error(`${configPath} does not exist`);
@@ -166,13 +226,36 @@ async function loadBundledConfig(rootDir, options) {
166
226
  }
167
227
  return Object.assign({}, config, { rootDir });
168
228
  }
169
- async function loadPackageJson(filepath) {
170
- try {
171
- const packageJson = await loadJson(filepath);
172
- return packageJson || {};
173
- } catch (err) {
174
- return {};
229
+ function esbuildExternalsPlugin(options) {
230
+ const rootDir = options.rootDir;
231
+ const allDeps = flattenPackageDepsFromMonorepo(rootDir);
232
+ function getPackageName(id) {
233
+ const segments = id.split("/");
234
+ if (segments.length > 1) {
235
+ if (segments[0].startsWith("@") && segments[0].length > 1) {
236
+ return `${segments[0]}/${segments[1]}`;
237
+ }
238
+ return segments[0];
239
+ }
240
+ return id;
175
241
  }
242
+ return {
243
+ name: "root-externals-plugin",
244
+ setup(build2) {
245
+ build2.onResolve({ filter: /.*/ }, (args) => {
246
+ const id = args.path;
247
+ if (id[0] !== "." && !id.startsWith("@/")) {
248
+ const packageName = getPackageName(id);
249
+ if (packageName in allDeps) {
250
+ return {
251
+ external: true
252
+ };
253
+ }
254
+ }
255
+ return null;
256
+ });
257
+ }
258
+ };
176
259
  }
177
260
 
178
261
  // src/node/vite.ts
@@ -257,11 +340,13 @@ export {
257
340
  fileExists,
258
341
  dirExists,
259
342
  directoryContains,
343
+ loadPackageJson,
344
+ getMonorepoPackageDeps,
345
+ flattenPackageDepsFromMonorepo,
260
346
  loadRootConfig,
261
347
  bundleRootConfig,
262
348
  loadBundledConfig,
263
- loadPackageJson,
264
349
  createViteServer,
265
350
  viteSsrLoadModule
266
351
  };
267
- //# sourceMappingURL=chunk-UJ6F5RQ5.js.map
352
+ //# sourceMappingURL=chunk-HTBDTUFE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/node/monorepo.ts","../src/utils/fsutils.ts","../src/node/load-config.ts","../src/node/vite.ts"],"sourcesContent":["import path from 'node:path';\nimport {getWorkspaces, getWorkspaceRoot, PackageInfo} from 'workspace-tools';\nimport {fileExistsSync, loadJsonSync} from '../utils/fsutils.js';\n\ninterface WorkspacePackage {\n name: string;\n path: string;\n packageJson: PackageInfo;\n}\n\nexport function loadPackageJson(filepath: string): PackageInfo | null {\n if (!fileExistsSync(filepath)) {\n return null;\n }\n return loadJsonSync(filepath);\n}\n\n/**\n * Returns a map of all packages in the monorepo and the corresponding\n * package.json path.\n */\nfunction getMonorepoPackages(\n rootDir: string\n): Record<string, WorkspacePackage> {\n const monorepoRoot = getWorkspaceRoot(rootDir);\n if (!monorepoRoot) {\n return {};\n }\n\n const workspaces = getWorkspaces(monorepoRoot);\n const packages: Record<string, WorkspacePackage> = {};\n workspaces.forEach((workspaceInfo) => {\n packages[workspaceInfo.name] = workspaceInfo;\n });\n return packages;\n}\n\n/**\n * Returns the top-level monorepo package's deps, if any.\n */\nexport function getMonorepoPackageDeps(\n rootDir: string\n): Record<string, string> {\n const monorepoRoot = getWorkspaceRoot(rootDir);\n if (!monorepoRoot) {\n return {};\n }\n\n const packageJsonPath = path.join(monorepoRoot, 'package.json');\n const packageJson = loadPackageJson(packageJsonPath);\n return packageJson?.dependencies || {};\n}\n\n/**\n * Flattens package.json deps from the root project dir, taking into account any\n * deps from the monorepo root as well as any `workspace:` deps from within the\n * monorepo.\n */\nexport function flattenPackageDepsFromMonorepo(\n rootDir: string,\n options?: {ignore?: Set<string>}\n): Record<string, string> {\n const packageJsonPath = path.resolve(rootDir, 'package.json');\n const packageJson = loadPackageJson(packageJsonPath);\n const monorepoDeps = getMonorepoPackageDeps(rootDir);\n\n // Flatten `peerDependencies` and `dependencies`.\n const projectDeps = {\n ...packageJson?.peerDependencies,\n ...packageJson?.dependencies,\n };\n\n const allDeps: Record<string, string> = {};\n const workspacePackages = getMonorepoPackages(rootDir);\n const ignore = options?.ignore || new Set();\n Object.entries(projectDeps).forEach(([depName, depVersion]) => {\n if (\n depName.startsWith('@blinkk/root') &&\n depVersion.startsWith('workspace:')\n ) {\n const packageInfo = workspacePackages[depName];\n if (packageInfo) {\n allDeps[depName] = packageInfo.packageJson.version;\n }\n } else if (depVersion.startsWith('workspace:')) {\n // For internal packages within the workspace, recursively collect the\n // deps from those packages.\n if (ignore.has(depName)) {\n return;\n }\n ignore.add(depName);\n const packageInfo = workspacePackages[depName];\n if (packageInfo) {\n const workspacePackageDir = packageInfo.path;\n const deps = flattenPackageDepsFromMonorepo(workspacePackageDir, {\n ignore: ignore,\n });\n for (const key in deps) {\n const currentValue = allDeps[key];\n if (\n deps[key] &&\n deps[key] !== '*' &&\n (!currentValue || currentValue === '*')\n ) {\n allDeps[key] = deps[key];\n }\n }\n }\n } else if (depVersion === '*' && monorepoDeps[depName]) {\n // For any dependencies using a wildcard version `*`, if the top-level\n // package.json has the depdenency defined, overwrite the version.\n allDeps[depName] = monorepoDeps[depName];\n } else {\n allDeps[depName] = depVersion;\n }\n });\n return sortDeps(allDeps);\n}\n\nfunction sortDeps(deps: Record<string, string>): Record<string, string> {\n const keys = Object.keys(deps).sort();\n const sortedDeps: Record<string, string> = {};\n for (const key of keys) {\n sortedDeps[key] = deps[key];\n }\n return sortedDeps;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport fsExtra from 'fs-extra';\nimport glob from 'tiny-glob';\n\nexport function isJsFile(filename: string) {\n return !!filename.match(/\\.(j|t)sx?$/);\n}\n\nexport async function writeFile(filepath: string, content: string) {\n const dirPath = path.dirname(filepath);\n await makeDir(dirPath);\n await fs.promises.writeFile(filepath, content);\n}\n\nexport async function makeDir(dirpath: string) {\n try {\n await fs.promises.access(dirpath);\n } catch (e) {\n await fs.promises.mkdir(dirpath, {recursive: true});\n }\n}\n\nexport async function copyDir(srcdir: string, dstdir: string) {\n if (!fsExtra.existsSync(srcdir)) {\n return;\n }\n fsExtra.copySync(srcdir, dstdir, {overwrite: true});\n}\n\n/**\n * Copies a glob of files from one directory to another.\n *\n * Example:\n *\n * ```\n * await copyGlob('*.css', 'src/styles', 'dist/html/styles');\n * ```\n */\nexport async function copyGlob(\n pattern: string,\n srcdir: string,\n dstdir: string\n) {\n const files = await glob(pattern, {cwd: srcdir});\n if (files.length > 0) {\n await makeDir(dstdir);\n }\n files.forEach((file) => {\n fsExtra.copySync(path.resolve(srcdir, file), path.resolve(dstdir, file));\n });\n}\n\nexport async function rmDir(dirpath: string) {\n await fs.promises.rm(dirpath, {recursive: true, force: true});\n}\n\nexport async function loadJson<T = unknown>(filepath: string): Promise<T> {\n const content = await fs.promises.readFile(filepath, 'utf-8');\n return JSON.parse(content);\n}\n\nexport function loadJsonSync<T = unknown>(filepath: string): T {\n const content = fs.readFileSync(filepath, 'utf-8');\n return JSON.parse(content);\n}\n\nexport async function writeJson(filepath: string, data: any) {\n const content = JSON.stringify(data, null, 2);\n await writeFile(filepath, content);\n}\n\nexport async function isDirectory(dirpath: string) {\n return fs.promises\n .stat(dirpath)\n .then((fsStat) => {\n return fsStat.isDirectory();\n })\n .catch((err) => {\n if (err.code === 'ENOENT') {\n return false;\n }\n throw err;\n });\n}\n\nexport function fileExists(filepath: string): Promise<boolean> {\n return fs.promises\n .access(filepath)\n .then(() => true)\n .catch(() => false);\n}\n\nexport function fileExistsSync(filepath: string): boolean {\n try {\n fs.accessSync(filepath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function dirExists(dirpath: string): Promise<boolean> {\n try {\n const stat = await fs.promises.stat(dirpath);\n return stat.isDirectory();\n } catch (error) {\n if (error.code === 'ENOENT') {\n return false;\n }\n throw error;\n }\n}\n\nexport async function directoryContains(\n dirpath: string,\n subpath: string\n): Promise<boolean> {\n const outer = await fs.promises.realpath(dirpath);\n const inner = await fs.promises.realpath(subpath);\n const rel = path.relative(outer, inner);\n return !rel.startsWith('..');\n}\n\nexport async function listFilesRecursive(dirPath: string): Promise<string[]> {\n const files: string[] = [];\n const entries = await fs.promises.readdir(dirPath, {withFileTypes: true});\n for (const entry of entries) {\n const fullPath = path.join(dirPath, entry.name);\n if (entry.isDirectory()) {\n const subFiles = await listFilesRecursive(fullPath);\n files.push(...subFiles);\n } else {\n files.push(fullPath);\n }\n }\n return files;\n}\n","import path from 'node:path';\nimport {bundleRequire} from 'bundle-require';\nimport {build, Plugin as EsbuildPlugin} from 'esbuild';\nimport {RootConfig} from '../core/config.js';\nimport {fileExists} from '../utils/fsutils.js';\nimport {flattenPackageDepsFromMonorepo} from './monorepo.js';\n\nexport interface ConfigOptions {\n command: string;\n}\n\nexport async function loadRootConfig(\n rootDir: string,\n options: ConfigOptions\n): Promise<RootConfig> {\n const configPath = path.resolve(rootDir, 'root.config.ts');\n const exists = await fileExists(configPath);\n if (!exists) {\n throw new Error(`${configPath} does not exist`);\n }\n const configBundle = await bundleRequire({\n filepath: configPath,\n esbuildOptions: {plugins: [esbuildExternalsPlugin({rootDir})]},\n });\n let config = configBundle.mod.default || {};\n if (typeof config === 'function') {\n config = (await config(options)) || {};\n }\n return Object.assign({}, config, {rootDir});\n}\n\n/**\n * Compiles a root.config.ts file to root.config.js.\n */\nexport async function bundleRootConfig(rootDir: string, outPath: string) {\n const configPath = path.resolve(rootDir, 'root.config.ts');\n const configExists = await fileExists(configPath);\n if (!configExists) {\n throw new Error(`${configPath} does not exist`);\n }\n await build({\n entryPoints: [configPath],\n bundle: true,\n minify: true,\n platform: 'node',\n outfile: outPath,\n sourcemap: 'inline',\n metafile: true,\n format: 'esm',\n plugins: [esbuildExternalsPlugin({rootDir})],\n });\n}\n\n/**\n * Loads a pre-bundled config file from dist/root.config.js.\n */\nexport async function loadBundledConfig(\n rootDir: string,\n options: ConfigOptions\n): Promise<RootConfig> {\n const configPath = path.resolve(rootDir, 'dist/root.config.js');\n const exists = await fileExists(configPath);\n if (!exists) {\n throw new Error(`${configPath} does not exist`);\n }\n const module = await import(configPath);\n let config = module.default || {};\n if (typeof config === 'function') {\n config = (await config(options)) || {};\n }\n return Object.assign({}, config, {rootDir});\n}\n\n/**\n * Externalizes node_modules deps from the package and any dependent packages\n * from the monorepo.\n */\nfunction esbuildExternalsPlugin(options: {rootDir: string}): EsbuildPlugin {\n const rootDir = options.rootDir;\n const allDeps = flattenPackageDepsFromMonorepo(rootDir);\n\n function getPackageName(id: string): string {\n const segments = id.split('/');\n if (segments.length > 1) {\n // Check if package is an org path like `@blinkk/root`.\n if (segments[0].startsWith('@') && segments[0].length > 1) {\n return `${segments[0]}/${segments[1]}`;\n }\n // For imports like `my-package/subpackage`, return `my-package`.\n return segments[0];\n }\n return id;\n }\n\n return {\n name: 'root-externals-plugin',\n setup(build) {\n build.onResolve({filter: /.*/}, (args) => {\n const id = args.path;\n if (id[0] !== '.' && !id.startsWith('@/')) {\n const packageName = getPackageName(id);\n if (packageName in allDeps) {\n return {\n external: true,\n };\n }\n }\n return null;\n });\n },\n };\n}\n","import {createServer, ViteDevServer} from 'vite';\nimport {RootConfig} from '../core/config.js';\nimport {getVitePlugins} from '../core/plugin.js';\n\nexport interface CreateViteServerOptions {\n /** Override HMR settings. */\n hmr?: boolean;\n /** The port the server will run on. */\n port?: number;\n /** List of files to include in the optimizeDeps.include config. */\n optimizeDeps?: string[];\n}\n\n/**\n * Returns a vite dev server.\n */\nexport async function createViteServer(\n rootConfig: RootConfig,\n options?: CreateViteServerOptions\n): Promise<ViteDevServer> {\n const rootDir = rootConfig.rootDir;\n const viteConfig = rootConfig.vite || {};\n\n let hmrOptions = viteConfig.server?.hmr;\n if (options?.hmr === false) {\n hmrOptions = false;\n } else if (typeof hmrOptions === 'undefined' && options?.port) {\n // Automatically set the HMR port to `port + 10`. This allows multiple\n // root.js dev servers to run without conflicts.\n hmrOptions = {port: options.port + 10};\n }\n\n const viteServer = await createServer({\n ...viteConfig,\n mode: 'development',\n root: rootDir,\n // publicDir is disabled from the vite dev server since it's handled by the\n // root dev server directly, which allows user middlewares to override\n // files in the public dir.\n publicDir: false,\n server: {\n ...(viteConfig.server || {}),\n middlewareMode: true,\n hmr: hmrOptions,\n },\n appType: 'custom',\n optimizeDeps: {\n // As of vite v5 / esbuild v19, experimentalDecorators need to be\n // explicitly set, and for some reason this option isn't read from the\n // project's tsconfig.json file by default.\n // See: https://vitejs.dev/blog/announcing-vite5\n esbuildOptions: {\n tsconfigRaw: {\n compilerOptions: {\n target: 'esnext',\n experimentalDecorators: true,\n useDefineForClassFields: false,\n },\n },\n },\n ...(viteConfig.optimizeDeps || {}),\n include: [\n ...(options?.optimizeDeps || []),\n ...(viteConfig.optimizeDeps?.include || []),\n ],\n extensions: [...(viteConfig.optimizeDeps?.extensions || []), '.tsx'],\n },\n ssr: {\n ...(viteConfig.ssr || {}),\n noExternal: ['@blinkk/root', '@blinkk/root-cms/richtext'],\n },\n esbuild: {\n ...(viteConfig.esbuild || {}),\n jsx: 'automatic',\n jsxImportSource: 'preact',\n },\n plugins: [\n ...(viteConfig.plugins || []),\n ...getVitePlugins(rootConfig.plugins || []),\n ],\n });\n return viteServer;\n}\n\n/**\n * Shortcut `viteServer.ssrLoadModule()` without starting an actual dev server.\n */\nexport async function viteSsrLoadModule(\n rootConfig: RootConfig,\n file: string\n): Promise<Record<string, any>> {\n const viteServer = await createViteServer(rootConfig, {hmr: false});\n const module = await viteServer.ssrLoadModule(file);\n await viteServer.close();\n return module;\n}\n"],"mappings":"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","names":["path","path","path","path","build"]}
@@ -32,4 +32,4 @@ export {
32
32
  configureServerPlugins,
33
33
  getVitePlugins
34
34
  };
35
- //# sourceMappingURL=chunk-ZUUGSC6Z.js.map
35
+ //# sourceMappingURL=chunk-MA6MSEP4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/plugin.ts"],"sourcesContent":["import {ViteDevServer, PluginOption as VitePlugin} from 'vite';\nimport {RootConfig} from './config.js';\nimport {NextFunction, Request, Response, Server} from './types.js';\n\ntype MaybePromise<T> = T | Promise<T>;\n\nexport type ConfigureServerHook = (\n server: Server,\n options: ConfigureServerOptions\n) => MaybePromise<void> | MaybePromise<() => void>;\n\nexport interface ConfigureServerOptions {\n type: 'dev' | 'preview' | 'prod';\n rootConfig: RootConfig;\n}\n\nexport interface PluginHooks {\n /**\n * Post-render hook that's called before the HTML is rendered to the response\n * object. If a string is returned from this hook, it will replace the\n * rendered HTML.\n */\n preRender: (html: string) => void | string | Promise<string>;\n}\n\nexport interface Plugin {\n [key: string]: any;\n /** The name of the plugin. */\n name?: string;\n /**\n * Configures the root.js express server. Any middleware defined by the plugin\n * will be added to the server first. If a callback fn is returned, it will\n * be called after the root.js middlewares are added.\n */\n configureServer?: ConfigureServerHook;\n /**\n * Hook for file changes.\n */\n onFileChange?: (\n eventName: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir',\n path: string\n ) => void;\n /**\n * Returns a list of deps to bundle for ssr. The files will be bundled and\n * output to `dist/server/`. The return value should be a map of\n * `{output filename => input filepath}`.\n *\n * E.g. a value of `{foo: 'path/to/bar.js'}` will output `dist/server/foo.js`.\n *\n * @experimental This config is subject to change to be incorporated into a\n * broader config option called \"ssr\" or \"ssrOptions\".\n */\n ssrInput?: () => {[entryAlias: string]: string};\n /** Adds vite plugins. */\n vitePlugins?: VitePlugin[];\n /** Plugin lifecycle callback hooks. */\n hooks?: PluginHooks;\n /** Custom 404 handler. */\n handle404?: (\n req: Request,\n res: Response,\n next: NextFunction\n ) => void | Promise<void>;\n}\n\n/**\n * Runs the pre-hook configureServer method of every plugin, calls a callback\n * function, and then runs the configureServer's post-hook if provided. Plugins\n * provide a post-hook by returning a callback function from configureServer.\n */\nexport async function configureServerPlugins(\n server: Server,\n callback: () => Promise<void>,\n plugins: Plugin[],\n options: ConfigureServerOptions\n) {\n const postHooks: Array<() => void> = [];\n const viteServer = server.get('viteServer') as ViteDevServer;\n\n // Call the `configureServer()` method for each plugin.\n for (const plugin of plugins) {\n if (plugin.configureServer) {\n const postHook = await plugin.configureServer(server, options);\n if (postHook) {\n postHooks.push(postHook);\n }\n }\n\n if (viteServer && plugin.onFileChange) {\n viteServer.watcher.on('all', plugin.onFileChange);\n }\n }\n\n // Register any built-in middleware.\n callback();\n\n // Run any post hooks returned by `plugin.configureServer()`.\n for (const postHook of postHooks) {\n await postHook();\n }\n}\n\nexport function getVitePlugins(plugins: Plugin[]): VitePlugin[] {\n const vitePlugins: VitePlugin[] = [];\n for (const plugin of plugins) {\n if (plugin.vitePlugins) {\n vitePlugins.push(...plugin.vitePlugins);\n }\n }\n return vitePlugins;\n}\n"],"mappings":";AAsEA,eAAsB,uBACpB,QACA,UACA,SACA,SACA;AACA,QAAM,YAA+B,CAAC;AACtC,QAAM,aAAa,OAAO,IAAI,YAAY;AAG1C,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,iBAAiB;AAC1B,YAAM,WAAW,MAAM,OAAO,gBAAgB,QAAQ,OAAO;AAC7D,UAAI,UAAU;AACZ,kBAAU,KAAK,QAAQ;AAAA,MACzB;AAAA,IACF;AAEA,QAAI,cAAc,OAAO,cAAc;AACrC,iBAAW,QAAQ,GAAG,OAAO,OAAO,YAAY;AAAA,IAClD;AAAA,EACF;AAGA,WAAS;AAGT,aAAW,YAAY,WAAW;AAChC,UAAM,SAAS;AAAA,EACjB;AACF;AAEO,SAAS,eAAe,SAAiC;AAC9D,QAAM,cAA4B,CAAC;AACnC,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,aAAa;AACtB,kBAAY,KAAK,GAAG,OAAO,WAAW;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { S as Server } from './types-RwR6rV2O.js';
1
+ import { S as Server } from './types-Mr1zFAT1.js';
2
2
  import 'express';
3
3
  import 'preact';
4
4
  import 'vite';
@@ -9,6 +9,7 @@ interface BuildOptions {
9
9
  ssrOnly?: boolean;
10
10
  mode?: string;
11
11
  concurrency?: string | number;
12
+ filter?: string;
12
13
  }
13
14
  declare function build(rootProjectDir?: string, options?: BuildOptions): Promise<void>;
14
15
 
@@ -18,6 +19,7 @@ interface CreatePackageOptions {
18
19
  out?: string;
19
20
  target?: DeployTarget;
20
21
  version?: string;
22
+ appYaml?: string;
21
23
  }
22
24
  declare function createPackage(rootProjectDir?: string, options?: CreatePackageOptions): Promise<void>;
23
25
 
@@ -53,4 +55,4 @@ declare class CliRunner {
53
55
  run(argv: string[]): Promise<void>;
54
56
  }
55
57
 
56
- export { CliRunner, build, createDevServer, createPackage, createPreviewServer, createProdServer, dev, preview, start };
58
+ export { type BuildOptions, CliRunner, build, createDevServer, createPackage, createPreviewServer, createProdServer, dev, preview, start };
package/dist/cli.js CHANGED
@@ -8,11 +8,11 @@ import {
8
8
  dev,
9
9
  preview,
10
10
  start
11
- } from "./chunk-7D26JHIF.js";
11
+ } from "./chunk-A4DNVP34.js";
12
12
  import "./chunk-DISVDCLA.js";
13
- import "./chunk-UJ6F5RQ5.js";
14
- import "./chunk-ZUUGSC6Z.js";
15
- import "./chunk-5YDJSEDK.js";
13
+ import "./chunk-HTBDTUFE.js";
14
+ import "./chunk-MA6MSEP4.js";
15
+ import "./chunk-3KGEENDW.js";
16
16
  export {
17
17
  CliRunner,
18
18
  build,
package/dist/core.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as Route } from './types-RwR6rV2O.js';
2
- export { j as ConfigureServerHook, k as ConfigureServerOptions, C as ContentSecurityPolicyConfig, p as GetStaticPaths, G as GetStaticProps, t as Handler, H as HandlerContext, w as HandlerRenderFn, v as HandlerRenderOptions, L as LocaleGroup, M as MultipartFile, N as NextFunction, l as Plugin, P as PluginHooks, r as Request, q as RequestMiddleware, s as Response, c as RootConfig, a as RootExperimentsConfig, f as RootHeaderConfig, d as RootI18nConfig, e as RootRedirectConfig, g as RootSecurityConfig, h as RootServerConfig, b as RootUserConfig, u as RouteModule, o as RouteParams, S as Server, x as Sitemap, y as SitemapItem, X as XFrameOptionsConfig, m as configureServerPlugins, i as defineConfig, n as getVitePlugins } from './types-RwR6rV2O.js';
1
+ import { R as Route } from './types-Mr1zFAT1.js';
2
+ export { j as ConfigureServerHook, k as ConfigureServerOptions, C as ContentSecurityPolicyConfig, v as GetStaticContent, p as GetStaticPaths, G as GetStaticProps, t as Handler, H as HandlerContext, y as HandlerRenderFn, x as HandlerRenderOptions, L as LocaleGroup, M as MultipartFile, N as NextFunction, l as Plugin, P as PluginHooks, r as Request, q as RequestMiddleware, s as Response, d as RootBuildConfig, b as RootConfig, f as RootHeaderConfig, c as RootI18nConfig, e as RootRedirectConfig, g as RootSecurityConfig, h as RootServerConfig, a as RootUserConfig, w as RouteModule, o as RouteParams, S as Server, z as Sitemap, A as SitemapItem, u as StaticContentResult, X as XFrameOptionsConfig, m as configureServerPlugins, i as defineConfig, n as getVitePlugins } from './types-Mr1zFAT1.js';
3
3
  import * as preact$1 from 'preact';
4
4
  import { FunctionalComponent, ComponentChildren } from 'preact';
5
5
  import 'express';
@@ -72,7 +72,9 @@ type HtmlProps = preact$1.JSX.HTMLAttributes<HTMLHtmlElement> & {
72
72
  */
73
73
  declare const Html: FunctionalComponent<HtmlProps>;
74
74
 
75
- type ScriptProps = preact.JSX.HTMLAttributes<HTMLScriptElement>;
75
+ type ScriptProps = preact.JSX.HTMLAttributes<HTMLScriptElement> & {
76
+ src?: string;
77
+ };
76
78
  /**
77
79
  * The <Script> component is used for rendering any custom script modules. At
78
80
  * the moment, the system only pre-renders and bundles files that are in the
@@ -87,7 +89,11 @@ type ScriptProps = preact.JSX.HTMLAttributes<HTMLScriptElement>;
87
89
  declare const Script: FunctionalComponent<ScriptProps>;
88
90
 
89
91
  type StringParamsContext = Record<string, string>;
90
- declare const StringParamsProvider: preact$1.Provider<StringParamsContext | null>;
92
+ interface StringParamsProviderProps {
93
+ value?: StringParamsContext;
94
+ children?: ComponentChildren;
95
+ }
96
+ declare const StringParamsProvider: FunctionalComponent<StringParamsProviderProps>;
91
97
  /**
92
98
  * A hook that returns a map of string params, configured via the
93
99
  * `StringParamsProvider` context provider. These params are automatically
@@ -115,6 +121,30 @@ declare const StringParamsProvider: preact$1.Provider<StringParamsContext | null
115
121
  */
116
122
  declare function useStringParams(): StringParamsContext;
117
123
 
124
+ type TransformFn = (str: string) => string;
125
+ interface TranslationMiddleware {
126
+ /** Transform the string before translation lookup. */
127
+ beforeTranslate?: TransformFn;
128
+ /** Transform the string after translation lookup. */
129
+ afterTranslate?: TransformFn;
130
+ /** Transform the string before `{param}` values are replaced. */
131
+ beforeReplaceParams?: TransformFn;
132
+ /** Transform the string after `{param}` values are replaced. */
133
+ afterReplaceParams?: TransformFn;
134
+ }
135
+ interface TranslationMiddlewareContext {
136
+ beforeTranslateFns: TransformFn[];
137
+ afterTranslateFns: TransformFn[];
138
+ beforeReplaceParamsFns: TransformFn[];
139
+ afterReplaceParamsFns: TransformFn[];
140
+ }
141
+ interface TranslationMiddlewareProviderProps {
142
+ value?: TranslationMiddleware;
143
+ children?: ComponentChildren;
144
+ }
145
+ declare const TranslationMiddlewareProvider: FunctionalComponent<TranslationMiddlewareProviderProps>;
146
+ declare function useTranslationMiddleware(): TranslationMiddlewareContext;
147
+
118
148
  interface I18nContext {
119
149
  locale: string;
120
150
  translations: Record<string, string>;
@@ -175,4 +205,4 @@ declare function useRequestContext(): RequestContext;
175
205
  */
176
206
  declare function useTranslations(): (str: string, params?: Record<string, string | number>) => string;
177
207
 
178
- export { Body, HTML_CONTEXT, Head, Html, type I18nContext, type RequestContext, Route, Script, type StringParamsContext, StringParamsProvider, getTranslations, useI18nContext, useRequestContext, useStringParams, useTranslations };
208
+ export { Body, HTML_CONTEXT, Head, Html, type I18nContext, type RequestContext, Route, Script, type StringParamsContext, StringParamsProvider, TranslationMiddlewareProvider, getTranslations, useI18nContext, useRequestContext, useStringParams, useTranslationMiddleware, useTranslations };
package/dist/core.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  configureServerPlugins,
3
3
  getVitePlugins
4
- } from "./chunk-ZUUGSC6Z.js";
4
+ } from "./chunk-MA6MSEP4.js";
5
5
  import {
6
6
  HTML_CONTEXT,
7
7
  Html,
@@ -56,17 +56,63 @@ var Script = (props) => {
56
56
  return null;
57
57
  };
58
58
 
59
- // src/core/hooks/useStringParams.ts
59
+ // src/core/hooks/useStringParams.tsx
60
60
  import { createContext } from "preact";
61
61
  import { useContext as useContext4 } from "preact/hooks";
62
+ import { jsx as jsx2 } from "preact/jsx-runtime";
62
63
  var STRING_PARAMS_CONTEXT = createContext(
63
64
  null
64
65
  );
65
- var StringParamsProvider = STRING_PARAMS_CONTEXT.Provider;
66
+ var StringParamsProvider = (props) => {
67
+ const parent = useContext4(STRING_PARAMS_CONTEXT) || {};
68
+ const merged = { ...parent, ...props.value };
69
+ return /* @__PURE__ */ jsx2(STRING_PARAMS_CONTEXT.Provider, { value: merged, children: props.children });
70
+ };
66
71
  function useStringParams() {
67
72
  return useContext4(STRING_PARAMS_CONTEXT) || {};
68
73
  }
69
74
 
75
+ // src/core/hooks/useTranslationsMiddleware.tsx
76
+ import { createContext as createContext2 } from "preact";
77
+ import { useContext as useContext5 } from "preact/hooks";
78
+ import { jsx as jsx3 } from "preact/jsx-runtime";
79
+ var TRANSLATION_MIDDLEWARE_CONTEXT = createContext2(null);
80
+ var TranslationMiddlewareProvider = (props) => {
81
+ const parent = useContext5(TRANSLATION_MIDDLEWARE_CONTEXT) || {
82
+ beforeTranslateFns: [],
83
+ afterTranslateFns: [],
84
+ beforeReplaceParamsFns: [],
85
+ afterReplaceParamsFns: []
86
+ };
87
+ const merged = {
88
+ beforeTranslateFns: [...parent.beforeTranslateFns],
89
+ afterTranslateFns: [...parent.afterTranslateFns],
90
+ beforeReplaceParamsFns: [...parent.beforeReplaceParamsFns],
91
+ afterReplaceParamsFns: [...parent.afterReplaceParamsFns]
92
+ };
93
+ if (props.value?.beforeTranslate) {
94
+ merged.beforeTranslateFns.push(props.value.beforeTranslate);
95
+ }
96
+ if (props.value?.afterTranslate) {
97
+ merged.afterTranslateFns.push(props.value.afterTranslate);
98
+ }
99
+ if (props.value?.beforeReplaceParams) {
100
+ merged.beforeReplaceParamsFns.push(props.value.beforeReplaceParams);
101
+ }
102
+ if (props.value?.afterReplaceParams) {
103
+ merged.afterReplaceParamsFns.push(props.value.afterReplaceParams);
104
+ }
105
+ return /* @__PURE__ */ jsx3(TRANSLATION_MIDDLEWARE_CONTEXT.Provider, { value: merged, children: props.children });
106
+ };
107
+ function useTranslationMiddleware() {
108
+ return useContext5(TRANSLATION_MIDDLEWARE_CONTEXT) || {
109
+ beforeTranslateFns: [],
110
+ afterTranslateFns: [],
111
+ beforeReplaceParamsFns: [],
112
+ afterReplaceParamsFns: []
113
+ };
114
+ }
115
+
70
116
  // src/core/hooks/useTranslations.ts
71
117
  function useTranslations() {
72
118
  let i18nContext = null;
@@ -77,14 +123,28 @@ function useTranslations() {
77
123
  }
78
124
  const translations = i18nContext?.translations || {};
79
125
  const stringParams = useStringParams();
126
+ const middleware = useTranslationMiddleware();
80
127
  const t = (str, params) => {
81
- const key = normalizeString(str);
82
- let translation = translations[key] ?? key ?? "";
83
- const allParams = { ...stringParams, ...params };
84
- for (const paramName of Object.keys(allParams)) {
85
- const paramValue = String(allParams[paramName] ?? "");
86
- translation = translation.replaceAll(`{${paramName}}`, paramValue);
128
+ let input = normalizeString(str);
129
+ middleware.beforeTranslateFns.forEach((fn) => {
130
+ input = fn(input);
131
+ });
132
+ let translation = translations[input] ?? input ?? "";
133
+ middleware.afterTranslateFns.forEach((fn) => {
134
+ translation = fn(translation);
135
+ });
136
+ middleware.beforeReplaceParamsFns.forEach((fn) => {
137
+ translation = fn(translation);
138
+ });
139
+ if (testHasStringParams(translation)) {
140
+ translation = replaceStringParams(translation, {
141
+ ...stringParams,
142
+ ...params
143
+ });
87
144
  }
145
+ middleware.afterReplaceParamsFns.forEach((fn) => {
146
+ translation = fn(translation);
147
+ });
88
148
  return translation;
89
149
  };
90
150
  return t;
@@ -96,6 +156,17 @@ function normalizeString(str) {
96
156
  function removeTrailingWhitespace(str) {
97
157
  return String(str).trimEnd().replace(/&nbsp;$/, "");
98
158
  }
159
+ function testHasStringParams(str) {
160
+ return str.includes("{") && str.includes("}");
161
+ }
162
+ function replaceStringParams(str, params) {
163
+ return str.replace(/{([^}]+)}/g, (match, key) => {
164
+ if (key in params) {
165
+ return String(params[key]);
166
+ }
167
+ return match;
168
+ });
169
+ }
99
170
  export {
100
171
  Body,
101
172
  HTML_CONTEXT,
@@ -103,6 +174,7 @@ export {
103
174
  Html,
104
175
  Script,
105
176
  StringParamsProvider,
177
+ TranslationMiddlewareProvider,
106
178
  configureServerPlugins,
107
179
  defineConfig,
108
180
  getTranslations,
@@ -110,6 +182,7 @@ export {
110
182
  useI18nContext,
111
183
  useRequestContext,
112
184
  useStringParams,
185
+ useTranslationMiddleware,
113
186
  useTranslations
114
187
  };
115
188
  //# sourceMappingURL=core.js.map