@budsbox/builder_vite 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/lib.d.ts CHANGED
@@ -1,31 +1,7 @@
1
- import type { Awaitable, Undef } from '@budsbox/lib-types';
2
- import { type ConfigEnv, type LibraryOptions, type UserConfig, type UserConfigExport, type UserConfigFnPromise } from 'vite';
3
- /**
4
- * Represents a custom user configuration function used to generate Vite configuration.
5
- *
6
- * @typeParam TOptions - The type of the custom options object, with a default to `object`.
7
- * @param viteEnv - A readonly object representing the Vite configuration environment.
8
- * @param options - An optional readonly object representing additional custom configuration options.
9
- * @returns A promise or value containing the generated Vite user configuration.
10
- */
11
- export type CustomUserConfigFn<TOptions extends object = object> = (viteEnv: Readonly<ConfigEnv>, options?: Undef<Readonly<TOptions>>) => Awaitable<UserConfig>;
12
- /**
13
- * A `ConfigFactory` is a function type that generates an asynchronous Vite's configuration object generator function.
14
- *
15
- * @param custom - An optional custom configuration of type `UserConfigExport`. It can be used
16
- * to override or extend default configurations.
17
- * @returns A function to be invoked by Vite to generate the final configuration object.
18
- */
19
- export type ConfigFactory = (custom?: UserConfigExport) => UserConfigFnPromise;
20
- /**
21
- * A `ConfigFactory` is a function type that generates an asynchronous Vite's configuration object generator function.
22
- *
23
- * @param custom - An optional custom configuration of type `UserConfigExport`. It can be used
24
- * to override or extend default configurations.
25
- * @param options - An optional object containing additional configuration options, specific to the factory.
26
- * @returns A function to be invoked by Vite to generate the final configuration object.
27
- */
28
- export type ConfigFactoryWithOptions<TOptions extends object> = (custom?: UserConfigExport, options?: Readonly<Partial<TOptions>>) => UserConfigFnPromise;
1
+ import type { PackageJson } from 'type-fest';
2
+ import type { ResolvedJson } from '@budsbox/lib-node/pckg';
3
+ import type { ConfigFactoryWithOptions, CustomUserConfigFn, ScopedNameGenerator } from './types.js';
4
+ import { type LibraryOptions, type UserConfigExport, type UserConfigFnPromise } from 'vite';
29
5
  /**
30
6
  * Creates a configuration factory that extends or modifies a base configuration.
31
7
  *
@@ -58,4 +34,16 @@ export declare const formatVarName: (packageName: string) => string;
58
34
  * where the extension is either `mjs` for `es` format or `cjs` for other formats.
59
35
  */
60
36
  export declare const formatFileName: Exclude<LibraryOptions['fileName'], string | undefined>;
37
+ /**
38
+ * Factory function for creating a `ScopedNameGenerator` that generates scoped,
39
+ * unique CSS class names based on file paths, package details, and additional rules.
40
+ *
41
+ * @param basePackage - The resolved package.json of the base package as a read-only object.
42
+ * This package serves as the reference point for relative path calculations and scoping.
43
+ * @param excludePathChunks - An optional array of path chunks to exclude from being used in
44
+ * generated scoped names. Defaults to ['src', 'dist', 'build', 'node_modules'].
45
+ * @returns A `ScopedNameGenerator` function that takes a local CSS class name and a file path
46
+ * as input and returns a generated scoped name.
47
+ */
48
+ export declare const generateScopedNameFactory: (basePackage: Readonly<ResolvedJson<PackageJson>>, excludePathChunks?: readonly string[]) => ScopedNameGenerator;
61
49
  //# sourceMappingURL=lib.d.ts.map
package/dist/lib.js CHANGED
@@ -1,7 +1,12 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { basename, dirname, relative } from 'node:path';
3
+ import cssesc from 'cssesc';
1
4
  import { mergeConfig, } from 'vite';
2
- import { isFunction, isNotNil } from '@budsbox/lib-es/guards';
5
+ import { createCachedFn } from '@budsbox/lib-es/function';
6
+ import { isFunction, isNil, isNotNil, isString } from '@budsbox/lib-es/guards';
3
7
  import { fif } from '@budsbox/lib-es/logical';
4
- import { camelCase, parsePackageName } from '@budsbox/lib-es/string';
8
+ import { camelCase, parsePackageName, splitPath } from '@budsbox/lib-es/string';
9
+ import { lookupFileSync } from '@budsbox/lib-node/fs';
5
10
  export function createConfigFactory(base) {
6
11
  return (custom, options) => async (env) => {
7
12
  const resolvedBase = await fif(await base, isFunction, (baseFn) => baseFn(env, options), (baseObj) => baseObj);
@@ -35,4 +40,78 @@ export const formatVarName = (packageName) => {
35
40
  * where the extension is either `mjs` for `es` format or `cjs` for other formats.
36
41
  */
37
42
  export const formatFileName = (format, entryName) => `${entryName}.${format === 'es' ? 'mjs' : 'cjs'}`;
43
+ /**
44
+ * Factory function for creating a `ScopedNameGenerator` that generates scoped,
45
+ * unique CSS class names based on file paths, package details, and additional rules.
46
+ *
47
+ * @param basePackage - The resolved package.json of the base package as a read-only object.
48
+ * This package serves as the reference point for relative path calculations and scoping.
49
+ * @param excludePathChunks - An optional array of path chunks to exclude from being used in
50
+ * generated scoped names. Defaults to ['src', 'dist', 'build', 'node_modules'].
51
+ * @returns A `ScopedNameGenerator` function that takes a local CSS class name and a file path
52
+ * as input and returns a generated scoped name.
53
+ */
54
+ export const generateScopedNameFactory = (basePackage, excludePathChunks = [
55
+ 'src',
56
+ 'dist',
57
+ 'build',
58
+ 'node_modules',
59
+ ]) => {
60
+ const excludeSet = new Set(excludePathChunks);
61
+ const { scope: baseScope } = parsePackageName(basePackage.json.name ?? 'anon', true);
62
+ const lookupCache = new Map();
63
+ const packageCache = new Map();
64
+ const scopedNameCache = new Map();
65
+ const scopedNameGenerator = (localName, filepath) => {
66
+ const foundPath = lookupFileSync({
67
+ startDir: dirname(filepath),
68
+ filename: 'package.json',
69
+ cache: lookupCache,
70
+ });
71
+ let pckgPrefix = '';
72
+ if (isString(foundPath)) {
73
+ if (foundPath !== basePackage.path) {
74
+ const pckg = readPackageJson(packageCache, foundPath);
75
+ const { scope, name } = parsePackageName(pckg.name ?? '', true);
76
+ pckgPrefix =
77
+ scope === baseScope || isNil(scope) ? name : `${scope}_-_${name}`;
78
+ }
79
+ }
80
+ else {
81
+ pckgPrefix = '-standalone-';
82
+ }
83
+ const subPath = relative(dirname(foundPath ?? basePackage.path), filepath);
84
+ const pathPart = splitPath(dirname(subPath))
85
+ .map((chunk) => (chunk === '..' ? '_--_' : chunk))
86
+ .filter((chunk) => !excludeSet.has(chunk))
87
+ .join('-');
88
+ const nameChunks = basename(filepath)
89
+ .split('.')
90
+ // remove extension
91
+ .slice(0, -1);
92
+ // remove `module` sub-extension
93
+ if (nameChunks.at(-1) === 'module') {
94
+ nameChunks.pop();
95
+ }
96
+ // remove common filename
97
+ if (nameChunks.at(-1) === 'style') {
98
+ nameChunks.pop();
99
+ }
100
+ return cssesc([
101
+ pckgPrefix,
102
+ [pathPart, nameChunks.join('-')].filter(Boolean).join('_'),
103
+ localName,
104
+ ]
105
+ .filter(Boolean)
106
+ .join('__'));
107
+ };
108
+ const cached = createCachedFn(scopedNameGenerator, (...args) => args.join(':'));
109
+ const generateScopedName = (localName, filepath) => cached(scopedNameCache, localName, filepath);
110
+ return generateScopedName;
111
+ };
112
+ const readPackageJson = createCachedFn((path) => {
113
+ if (!path.endsWith('package.json'))
114
+ throw new Error(`Not a package.json path: ${path}`);
115
+ return JSON.parse(readFileSync(path, 'utf-8'));
116
+ });
38
117
  //# sourceMappingURL=lib.js.map
package/dist/plain.d.ts CHANGED
@@ -1,3 +1,20 @@
1
+ import { type PluginOptions } from 'vite-plugin-react-rich-svg';
2
+ /**
3
+ * Extended configuration options for the `vite-plugin-react-rich-svg` plugin.
4
+ *
5
+ * @see https://github.com/iGoodie/vite-plugin-react-rich-svg?tab=readme-ov-file#plugin-configurations
6
+ */
7
+ export interface CustomReactRichSvgOptions extends PluginOptions {
8
+ /**
9
+ * Enables/disables SVGO optimization for the whole plugin.
10
+ * Defaults to `true` when `NODE_ENV` is `production`. May be overridden by sub-options (like `rawLoaderOptions.svgoEnabled`).
11
+ */
12
+ svgoEnabled?: boolean;
13
+ /**
14
+ * Default SVGO configuration for the whole plugin.
15
+ */
16
+ svgoConfig?: NonNullable<PluginOptions['rawLoaderOptions']>['svgoConfig'];
17
+ }
1
18
  /**
2
19
  * Represents configuration options for plain configurations.
3
20
  */
@@ -12,14 +29,16 @@ export interface PlainConfigOptions {
12
29
  lib?: boolean;
13
30
  /**
14
31
  * An array of strings representing the chunks to exclude from the path part when generating scoped names for CSS modules.
15
- *
16
- * @default ['src']
17
32
  */
18
33
  generateScopedNameExcludedPathChunks?: readonly string[];
19
34
  /**
20
35
  * Whether to add the scope of the package to the conditions for module `exports` resolution.
21
36
  */
22
37
  addScopeToConditions?: boolean;
38
+ /**
39
+ * Options for the `vite-plugin-react-rich-svg` plugin.
40
+ */
41
+ reactRichSvgOptions?: CustomReactRichSvgOptions;
23
42
  }
24
- export declare const usePlainConfig: import("./lib.js").ConfigFactoryWithOptions<PlainConfigOptions>;
43
+ export declare const usePlainConfig: import("./types.js").ConfigFactoryWithOptions<PlainConfigOptions>;
25
44
  //# sourceMappingURL=plain.d.ts.map
package/dist/plain.js CHANGED
@@ -1,75 +1,58 @@
1
- import { readFileSync } from 'node:fs';
2
- import { basename, dirname, relative } from 'node:path';
3
- import cssesc from 'cssesc';
1
+ import { env } from 'node:process';
4
2
  import { NodePackageImporter } from 'sass-embedded';
5
3
  import { defaultClientConditions } from 'vite';
6
- import { createCachedFn } from '@budsbox/lib-es/function';
7
- import { isNil, isNotNil, isString } from '@budsbox/lib-es/guards';
4
+ import richSvg from 'vite-plugin-react-rich-svg';
5
+ import { isNotNil } from '@budsbox/lib-es/guards';
8
6
  import { fifs } from '@budsbox/lib-es/logical';
9
- import { parsePackageName, splitPath } from '@budsbox/lib-es/string';
10
- import { lookupFileSync } from '@budsbox/lib-node/fs';
7
+ import { parsePackageName } from '@budsbox/lib-es/string';
11
8
  import { findCurrentPackageJson } from '@budsbox/lib-node/pckg';
12
9
  import packageJson from '#package.json' with { type: 'json' };
13
- import { createConfigFactory, formatFileName, formatVarName } from './lib.js';
14
- const readPackageJson = createCachedFn((path) => {
15
- if (!path.endsWith('package.json'))
16
- throw new Error(`Not a package.json path: ${path}`);
17
- return JSON.parse(readFileSync(path, 'utf-8'));
18
- });
19
- export const usePlainConfig = createConfigFactory(async ({ mode }, { importMeta, lib = false, generateScopedNameExcludedPathChunks = ['src'], addScopeToConditions = false, } = {}) => {
20
- const runnerPackage = await findCurrentPackageJson(importMeta);
21
- const { scope: runnerScope } = parsePackageName(runnerPackage.json.name ?? 'anon', true);
22
- const lookupCache = new Map();
23
- const packageCache = new Map();
24
- const excludeChunks = new Set(generateScopedNameExcludedPathChunks);
10
+ import { createConfigFactory, formatFileName, formatVarName, generateScopedNameFactory, } from './lib.js';
11
+ export const usePlainConfig = createConfigFactory(async ({ mode }, { importMeta, lib = false, generateScopedNameExcludedPathChunks, addScopeToConditions = false,
12
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13
+ reactRichSvgOptions = {}, } = {}) => {
14
+ const basePackage = await findCurrentPackageJson(importMeta);
15
+ const { scope: baseScope } = parsePackageName(basePackage.json.name ?? 'anon', true);
25
16
  const clientConditions = ((addScopeToConditions ||
26
17
  // enabled by default in this monorepo
27
- sameScope(packageJson, runnerPackage.json)) &&
28
- isNotNil(runnerScope)) ?
29
- [runnerScope, ...defaultClientConditions]
18
+ sameScope(packageJson, basePackage.json)) &&
19
+ isNotNil(baseScope)) ?
20
+ [baseScope, ...defaultClientConditions]
30
21
  : [...defaultClientConditions];
31
- const generateScopedName = createCachedFn((localName, filepath) => {
32
- const foundPath = lookupFileSync({
33
- startDir: dirname(filepath),
34
- filename: 'package.json',
35
- cache: lookupCache,
36
- });
37
- let pckgPrefix = '';
38
- if (isString(foundPath)) {
39
- if (foundPath !== runnerPackage.path) {
40
- const pckg = readPackageJson(packageCache, foundPath);
41
- const { scope, name } = parsePackageName(pckg.name ?? '', true);
42
- pckgPrefix =
43
- scope === runnerScope || isNil(scope) ?
44
- name
45
- : `${scope}_-_${name}`;
46
- }
47
- }
48
- else {
49
- pckgPrefix = '-standalone-';
50
- }
51
- const subPath = relative(dirname(foundPath ?? runnerPackage.path), filepath);
52
- const pathPart = splitPath(dirname(subPath))
53
- .map((chunk) => (chunk === '..' ? '_--_' : chunk))
54
- .filter((chunk) => !excludeChunks.has(chunk))
55
- .join('-');
56
- const nameChunks = basename(filepath).split('.').slice(0, -1);
57
- if (nameChunks.at(-1) === 'module') {
58
- nameChunks.pop();
59
- }
60
- if (nameChunks.at(-1) === 'style') {
61
- nameChunks.pop();
62
- }
63
- return cssesc([
64
- pckgPrefix,
65
- [pathPart, nameChunks.join('-')].filter(Boolean).join('_'),
66
- localName,
67
- ]
68
- .filter(Boolean)
69
- .join('__'));
70
- }, (...args) => args.join(':'));
71
- const scopedNameCache = new Map();
22
+ const svgoEnabled = reactRichSvgOptions.svgoEnabled ?? env.NODE_ENV === 'production';
23
+ const svgoConfig = reactRichSvgOptions.svgoConfig ?? {};
72
24
  return {
25
+ plugins: [
26
+ richSvg({
27
+ ...reactRichSvgOptions,
28
+ base64LoaderOptions: {
29
+ svgoEnabled,
30
+ svgoConfig,
31
+ ...reactRichSvgOptions.base64LoaderOptions,
32
+ },
33
+ componentLoaderOptions: {
34
+ ...reactRichSvgOptions.componentLoaderOptions,
35
+ svgrConfig: {
36
+ svgo: svgoEnabled,
37
+ svgoConfig,
38
+ ...reactRichSvgOptions.componentLoaderOptions?.svgrConfig,
39
+ },
40
+ },
41
+ rawLoaderOptions: {
42
+ svgoEnabled,
43
+ svgoConfig,
44
+ ...reactRichSvgOptions.rawLoaderOptions,
45
+ },
46
+ urlLoaderOptions: {
47
+ svgoEnabled,
48
+ svgoConfig,
49
+ ...reactRichSvgOptions.urlLoaderOptions,
50
+ },
51
+ }),
52
+ ],
53
+ resolve: {
54
+ conditions: clientConditions,
55
+ },
73
56
  root: 'src',
74
57
  build: {
75
58
  outDir: '../dist',
@@ -77,19 +60,16 @@ export const usePlainConfig = createConfigFactory(async ({ mode }, { importMeta,
77
60
  ...fifs(lib, {
78
61
  lib: {
79
62
  entry: 'index.ts',
80
- name: formatVarName(runnerPackage.json.name ?? '_anon_'),
63
+ name: formatVarName(basePackage.json.name ?? '_anon_'),
81
64
  fileName: formatFileName,
82
65
  cssFileName: 'index',
83
66
  },
84
67
  }),
85
68
  },
86
- resolve: {
87
- conditions: clientConditions,
88
- },
89
69
  css: {
90
70
  modules: {
91
71
  localsConvention: 'camelCaseOnly',
92
- generateScopedName: mode === 'production' ? '[hash:hex]' : ((localName, filepath) => generateScopedName(scopedNameCache, localName, filepath)),
72
+ generateScopedName: mode === 'production' ? '[hash:hex]' : (generateScopedNameFactory(basePackage, generateScopedNameExcludedPathChunks)),
93
73
  },
94
74
  preprocessorOptions: {
95
75
  scss: {
package/dist/react.d.ts CHANGED
@@ -4,5 +4,5 @@ import { type PlainConfigOptions } from './plain.js';
4
4
  */
5
5
  export interface ReactConfigOptions extends PlainConfigOptions {
6
6
  }
7
- export declare const useReactConfig: import("./lib.js").ConfigFactoryWithOptions<ReactConfigOptions>;
7
+ export declare const useReactConfig: import("./types.js").ConfigFactoryWithOptions<ReactConfigOptions>;
8
8
  //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1,38 @@
1
+ import type { ConfigEnv, UserConfig, UserConfigExport, UserConfigFnPromise } from 'vite';
2
+ import type { Awaitable, Undef } from '@budsbox/lib-types';
3
+ /**
4
+ * Represents a custom user configuration function used to generate Vite configuration.
5
+ *
6
+ * @typeParam TOptions - The type of the custom options object, with a default to `object`.
7
+ * @param viteEnv - A readonly object representing the Vite configuration environment.
8
+ * @param options - An optional readonly object representing additional custom configuration options.
9
+ * @returns A promise or value containing the generated Vite user configuration.
10
+ */
11
+ export type CustomUserConfigFn<TOptions extends object = object> = (viteEnv: Readonly<ConfigEnv>, options?: Undef<Readonly<TOptions>>) => Awaitable<UserConfig>;
12
+ /**
13
+ * A `ConfigFactory` is a function type that generates an asynchronous Vite's configuration object generator function.
14
+ *
15
+ * @param custom - An optional custom configuration of type `UserConfigExport`. It can be used
16
+ * to override or extend default configurations.
17
+ * @returns A function to be invoked by Vite to generate the final configuration object.
18
+ */
19
+ export type ConfigFactory = (custom?: UserConfigExport) => UserConfigFnPromise;
20
+ /**
21
+ * A `ConfigFactory` is a function type that generates an asynchronous Vite's configuration object generator function.
22
+ *
23
+ * @param custom - An optional custom configuration of type `UserConfigExport`. It can be used
24
+ * to override or extend default configurations.
25
+ * @param options - An optional object containing additional configuration options, specific to the factory.
26
+ * @returns A function to be invoked by Vite to generate the final configuration object.
27
+ */
28
+ export type ConfigFactoryWithOptions<TOptions extends object> = (custom?: UserConfigExport, options?: Readonly<Partial<TOptions>>) => UserConfigFnPromise;
29
+ /**
30
+ * A type definition for a function that generates a scoped class name for a given input.
31
+ * This is used in CSS module transformations.
32
+ *
33
+ * @param localName - The local name of the class or element.
34
+ * @param filename - The filename of the source file.
35
+ * @returns A scoped class name.
36
+ */
37
+ export type ScopedNameGenerator = (this: void, localName: string, filename: string) => string;
38
+ //# sourceMappingURL=types.d.ts.map
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@budsbox/builder_vite",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "homepage": "https://gitlab.com/budsbox/fe/seed",
5
5
  "bugs": {
6
6
  "url": "https://gitlab.com/budsbox/fe/seed/-/issues"
@@ -10,13 +10,19 @@
10
10
  "author": "Konstantin Kutsyllo <trikadin@pm.me>",
11
11
  "type": "module",
12
12
  "imports": {
13
- "#package.json": "./package.json"
13
+ "#package.json": "./package.json",
14
+ "#client": {
15
+ "types": "./client.d.ts"
16
+ }
14
17
  },
15
18
  "exports": {
16
19
  ".": {
17
20
  "import": "./dist/index.js",
18
21
  "types": "./dist/index.d.ts"
19
22
  },
23
+ "./client": {
24
+ "types": "./client.d.ts"
25
+ },
20
26
  "./package.json": "./package.json"
21
27
  },
22
28
  "files": [
@@ -29,17 +35,18 @@
29
35
  },
30
36
  "dependencies": {
31
37
  "@budsbox/lib-es": "^2.3.0",
32
- "@budsbox/lib-node": "^1.1.0",
38
+ "@budsbox/lib-node": "^1.1.1",
33
39
  "@types/node": "^22.15.2",
34
40
  "cssesc": "^3.0.0",
41
+ "ts-deepmerge": "^7.0.3",
35
42
  "tslib": "^2.8.1",
36
43
  "type-fest": "^4.32.0"
37
44
  },
38
45
  "devDependencies": {
39
- "@budsbox/eslint": "^1.2.0",
40
- "@budsbox/eslint_presets-node-lib": "^1.0.4",
41
- "@budsbox/eslint_presets-tools": "^1.0.4",
42
- "@budsbox/lib-types": "^1.2.0",
46
+ "@budsbox/eslint": "^1.2.1",
47
+ "@budsbox/eslint_presets-node-lib": "^1.0.5",
48
+ "@budsbox/eslint_presets-tools": "^1.0.5",
49
+ "@budsbox/lib-types": "^1.3.0",
43
50
  "@budsbox/tsconfigs": "^4.3.1",
44
51
  "@types/cssesc": "^3",
45
52
  "@types/eslint": "^9.6.1",
@@ -48,13 +55,15 @@
48
55
  "eslint": "^9.26.0",
49
56
  "sass-embedded": "^1.92.1",
50
57
  "typescript": "^5.8.3",
51
- "vite": "^7.1.5"
58
+ "vite": "^7.1.5",
59
+ "vite-plugin-react-rich-svg": "1.x"
52
60
  },
53
61
  "peerDependencies": {
54
62
  "@vitejs/plugin-react": "^5.0.3",
55
63
  "babel-plugin-react-compiler": "^19.1.0-rc.3",
56
64
  "sass-embedded": "^1.92.1",
57
- "vite": "^7.1.5"
65
+ "vite": "^7.1.5",
66
+ "vite-plugin-react-rich-svg": "1.x"
58
67
  },
59
68
  "packageManager": "yarn@4.9.2"
60
69
  }