@vitus-labs/tools-core 1.9.1-alpha.9 → 1.10.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.
package/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # @vitus-labs/tools-core
2
+
3
+ Shared utilities for config loading, package metadata, and file discovery.
4
+
5
+ This is the foundation package used by all other `@vitus-labs/tools-*` packages.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ bun add @vitus-labs/tools-core
11
+ ```
12
+
13
+ ## API
14
+
15
+ ### `defineConfig(config)`
16
+
17
+ Identity helper for typed config files:
18
+
19
+ ```js
20
+ // vl-tools.config.mjs
21
+ import { defineConfig } from '@vitus-labs/tools-core'
22
+
23
+ export default defineConfig({
24
+ build: { sourceDir: 'src', outputDir: 'lib' },
25
+ stories: { framework: 'next' },
26
+ })
27
+ ```
28
+
29
+ ### `PKG`
30
+
31
+ Parsed `package.json` of the consuming project, augmented with:
32
+
33
+ - `bundleName` — camelCase package name (e.g. `@my-org/my-lib` → `myOrgMyLib`)
34
+ - `externalDependencies` — merged `dependencies` + `peerDependencies` keys
35
+
36
+ ### `VL_CONFIG`
37
+
38
+ Loaded config from `vl-tools.config.mjs`. Returns a function to access config sections:
39
+
40
+ ```ts
41
+ const buildConfig = VL_CONFIG('build')
42
+ buildConfig.get('sourceDir', 'src') // read with default
43
+ buildConfig.merge({ outputDir: 'dist' }) // deep-merge
44
+ ```
45
+
46
+ Config files cascade: root configs load first, closest package config overrides.
47
+
48
+ ### `TS_CONFIG`
49
+
50
+ Parsed `tsconfig.json` of the consuming project.
51
+
52
+ ### `findFile(filename)`
53
+
54
+ Walks up the directory tree from `cwd` to find a file by name.
55
+
56
+ ### `loadFileToJSON(filename)`
57
+
58
+ Finds and parses a JSON file from the directory tree.
59
+
60
+ ### `loadConfigParam(filename)`
61
+
62
+ Returns a function `(key, defaultValue)` to read dot-path keys from a JSON config file.
63
+
64
+ ### `swapGlobals(globals)`
65
+
66
+ Inverts key/value pairs — used to convert rollup `globals` format.
67
+
68
+ ## Note
69
+
70
+ `PKG`, `VL_CONFIG`, and `TS_CONFIG` are computed at module load time using top-level `await`. Importing this package has side effects (reads `package.json`, `tsconfig.json`, and `vl-tools.config.mjs` from `cwd`).
71
+
72
+ ## License
73
+
74
+ MIT
package/lib/index.js CHANGED
@@ -20,6 +20,8 @@ const get = (obj, dotPath, defaultValue = {}) => {
20
20
  const deepMerge = (target, source) => {
21
21
  const result = { ...target };
22
22
  for (const key of Object.keys(source)) {
23
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype')
24
+ continue;
23
25
  const srcVal = source[key];
24
26
  const tgtVal = result[key];
25
27
  if (typeof srcVal === 'object' &&
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\nconst VL_CONFIG_FILES = ['vl-tools.config.mjs']\nconst PACKAGE_FILE_NAME = 'package.json'\nconst TYPESCRIPT_FILE_NAME = 'tsconfig.json'\n\n// --------------------------------------------------------\n// Utility helpers (replaces lodash-es and find-up)\n// --------------------------------------------------------\nconst get = (obj: any, dotPath: string, defaultValue: any = {}): any => {\n const keys = dotPath.split('.')\n let result = obj\n\n for (const key of keys) {\n if (result == null) return defaultValue\n result = result[key]\n }\n\n return result === undefined ? defaultValue : result\n}\n\nconst deepMerge = (\n target: Record<string, any>,\n source: Record<string, any>,\n): Record<string, any> => {\n const result = { ...target }\n\n for (const key of Object.keys(source)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype')\n continue\n\n const srcVal = source[key]\n const tgtVal = result[key]\n\n if (\n typeof srcVal === 'object' &&\n srcVal !== null &&\n !Array.isArray(srcVal) &&\n typeof tgtVal === 'object' &&\n tgtVal !== null &&\n !Array.isArray(tgtVal)\n ) {\n result[key] = deepMerge(tgtVal, srcVal)\n } else {\n result[key] = srcVal\n }\n }\n\n return result\n}\n\nconst findFileUp = (\n names: string | string[],\n cwd = process.cwd(),\n): string | undefined => {\n const fileNames = Array.isArray(names) ? names : [names]\n let dir = path.resolve(cwd)\n\n while (true) {\n for (const name of fileNames) {\n const filePath = path.join(dir, name)\n try {\n if (fs.statSync(filePath).isFile()) return filePath\n } catch (_e) {\n // file doesn't exist, continue\n }\n }\n\n const parent = path.dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\n// --------------------------------------------------------\n// FIND & READ file helpers\n// --------------------------------------------------------\nconst findFile = (filename: string) => findFileUp(filename)\n\nconst loadFileToJSON = (filename: string): Record<string, any> => {\n const file = findFile(filename)\n if (!file) return {}\n\n try {\n return JSON.parse(fs.readFileSync(file, 'utf-8'))\n } catch (_e) {\n return {}\n }\n}\n\nconst loadModuleAsync = async (\n filePath: string,\n): Promise<Record<string, any>> => {\n try {\n const mod = await import(pathToFileURL(filePath).href)\n return mod?.default ?? mod ?? {}\n } catch (e: any) {\n console.warn(\n `[tools-core] Failed to load config: ${filePath}\\n ${e.message}`,\n )\n return {}\n }\n}\n\n// --------------------------------------------------------\n// GET PACKAGE.JSON info\n// --------------------------------------------------------\nconst getPackageJSON = () => loadFileToJSON(PACKAGE_FILE_NAME)\n\n// --------------------------------------------------------\n// PACKAGE.json parsing functions\n// --------------------------------------------------------\n\n// GET LIST OF DEPENDENCIES from package.json\nconst getDependenciesList = (types: any) => {\n const pkg = getPackageJSON()\n let result: any = []\n\n types.forEach((item: any) => {\n const data = pkg[item]\n result = [...result, ...Object.keys(data || {})]\n })\n\n return result\n}\n\n// converts package name to umd or iife valid format\n// example: napespace-package-name => namespacePackageName\nconst camelspaceBundleName = (name: string) => {\n const parsedName = name.replace('@', '').replace('/', '-')\n const toCamelCase = (items: any) =>\n items.map((item: any, i: any) =>\n i === 0\n ? item\n : item.charAt(0).toUpperCase() + item.slice(1).toLowerCase(),\n )\n const parts = parsedName.split('-')\n const result = toCamelCase(parts).join('')\n\n return result\n}\n\n// --------------------------------------------------------\n// PACKAGE JSON DATA\n// --------------------------------------------------------\nconst getPkgData = (): Record<string, any> => {\n const pkg = getPackageJSON()\n const { name } = pkg\n\n return {\n ...pkg,\n bundleName: camelspaceBundleName(name),\n externalDependencies: getDependenciesList([\n 'dependencies',\n 'peerDependencies',\n ]),\n }\n}\n\n// --------------------------------------------------------\n// LOAD EXTERNAL CONFIGURATION\n// Cascading: finds all vl-tools.config.mjs files from\n// cwd upward, then deep-merges them (root first, closest\n// package config wins).\n// --------------------------------------------------------\nconst findAllConfigFiles = (): string[] => {\n const files: string[] = []\n let cwd = process.cwd()\n\n while (true) {\n const file = findFileUp(VL_CONFIG_FILES, cwd)\n if (!file) break\n files.push(file)\n const parentDir = path.dirname(path.dirname(file))\n if (parentDir === path.dirname(file)) break\n cwd = parentDir\n }\n\n // Root config first, closest config last (overrides)\n return files.reverse()\n}\n\nconst getExternalConfig = async (): Promise<Record<string, any>> => {\n const files = findAllConfigFiles()\n let config: Record<string, any> = {}\n\n for (const file of files) {\n const loaded = await loadModuleAsync(file)\n config = deepMerge(config, loaded)\n }\n\n return config\n}\n\nconst loadConfigParam =\n (filename: string) =>\n (key: string, defaultValue = {}) => {\n const externalConfig = loadFileToJSON(filename)\n\n return get(externalConfig, key, defaultValue)\n }\n\nconst loadVLToolsConfig = async () => {\n const externalConfig = await getExternalConfig()\n\n const cloneAndEnhance = (object: Record<string, any>) => ({\n get config() {\n return object\n },\n get: (param: string, defaultValue?: any) =>\n get(object, param, defaultValue || {}),\n merge: (param: Record<string, any>) =>\n cloneAndEnhance(deepMerge(param, object)),\n })\n\n const getOutput = (key: string) => {\n const result = get(externalConfig, key, {})\n\n return cloneAndEnhance(result)\n }\n\n return getOutput\n}\n\nconst defineConfig = <T extends Record<string, any>>(config: T): T => config\n\nconst swapGlobals = (globals: Record<string, string>) =>\n Object.entries(globals).reduce<Record<string, string>>(\n (acc, [key, value]) => {\n acc[value] = key\n return acc\n },\n {},\n )\n\nconst PKG = getPkgData()\nconst VL_CONFIG = await loadVLToolsConfig()\nconst TS_CONFIG = loadFileToJSON(TYPESCRIPT_FILE_NAME)\n\nexport {\n defineConfig,\n findFile,\n loadConfigParam,\n loadFileToJSON,\n loadVLToolsConfig,\n swapGlobals,\n PKG,\n VL_CONFIG,\n TS_CONFIG,\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AA4EA,QAAA,MAAM,QAAQ,GAAI,UAAU,MAAM,uBAAyB,CAAA;AAE3D,QAAA,MAAM,cAAc,GAAI,UAAU,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAS5D,CAAA;AA0GD,QAAA,MAAM,eAAe,GAClB,UAAU,MAAM,MAChB,KAAK,MAAM,EAAE,iBAAiB,QAI9B,CAAA;AAEH,QAAA,MAAM,iBAAiB,sBAaG,MAAM;;iBANf,MAAM,iBAAiB,GAAG;mBAExB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;EAWrC,CAAA;AAED,QAAA,MAAM,YAAY,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,KAAG,CAAW,CAAA;AAE5E,QAAA,MAAM,WAAW,GAAI,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,2BAOjD,CAAA;AAEH,QAAA,MAAM,GAAG,qBAAe,CAAA;AACxB,QAAA,MAAM,SAAS,QArBW,MAAM;;iBANf,MAAM,iBAAiB,GAAG;mBAExB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;CAyBK,CAAA;AAC3C,QAAA,MAAM,SAAS,qBAAuC,CAAA;AAEtD,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,GAAG,EACH,SAAS,EACT,SAAS,GACV,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AA+EA,QAAA,MAAM,QAAQ,GAAI,UAAU,MAAM,uBAAyB,CAAA;AAE3D,QAAA,MAAM,cAAc,GAAI,UAAU,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAS5D,CAAA;AA0GD,QAAA,MAAM,eAAe,GAClB,UAAU,MAAM,MAChB,KAAK,MAAM,EAAE,iBAAiB,QAI9B,CAAA;AAEH,QAAA,MAAM,iBAAiB,sBAaG,MAAM;;iBANf,MAAM,iBAAiB,GAAG;mBAExB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;EAWrC,CAAA;AAED,QAAA,MAAM,YAAY,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,KAAG,CAAW,CAAA;AAE5E,QAAA,MAAM,WAAW,GAAI,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,2BAOjD,CAAA;AAEH,QAAA,MAAM,GAAG,qBAAe,CAAA;AACxB,QAAA,MAAM,SAAS,QArBW,MAAM;;iBANf,MAAM,iBAAiB,GAAG;mBAExB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;CAyBK,CAAA;AAC3C,QAAA,MAAM,SAAS,qBAAuC,CAAA;AAEtD,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,GAAG,EACH,SAAS,EACT,SAAS,GACV,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitus-labs/tools-core",
3
- "version": "1.9.1-alpha.9+b513757",
3
+ "version": "1.10.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,14 +24,17 @@
24
24
  "publishConfig": {
25
25
  "access": "public"
26
26
  },
27
+ "files": [
28
+ "lib/"
29
+ ],
27
30
  "scripts": {
28
31
  "prepublish": "bun run build",
29
32
  "build": "tsc",
30
33
  "typecheck": "tsc --noEmit"
31
34
  },
32
35
  "devDependencies": {
33
- "@vitus-labs/tools-typescript": "1.9.1-alpha.9+b513757",
36
+ "@vitus-labs/tools-typescript": "1.10.0",
34
37
  "typescript": "^5.9.3"
35
38
  },
36
- "gitHead": "b51375767bb010559a1e11f6e4d6141b771c07a6"
39
+ "gitHead": "803c33304f997f9585590d1f66a755e553ea23e5"
37
40
  }
package/CHANGELOG.md DELETED
@@ -1,16 +0,0 @@
1
- # Change Log
2
-
3
- All notable changes to this project will be documented in this file.
4
- See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
-
6
- ## [1.5.2-alpha.1](https://github.com/vitus-labs/tools/compare/v1.5.2-alpha.0...v1.5.2-alpha.1) (2026-02-07)
7
-
8
- **Note:** Version bump only for package @vitus-labs/tools-core
9
-
10
-
11
-
12
-
13
-
14
- ## [1.5.2-alpha.0](https://github.com/vitus-labs/tools/compare/v1.5.1...v1.5.2-alpha.0) (2026-02-06)
15
-
16
- **Note:** Version bump only for package @vitus-labs/tools-core
package/src/index.test.ts DELETED
@@ -1,345 +0,0 @@
1
- import { mkdirSync, rmSync, writeFileSync } from 'node:fs'
2
- import { tmpdir } from 'node:os'
3
- import path from 'node:path'
4
- import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest'
5
-
6
- const BASE_TMP = path.join(tmpdir(), `vl-core-test-${Date.now()}`)
7
- let testId = 0
8
-
9
- const createTestDir = (opts: {
10
- packageJson?: Record<string, any>
11
- tsConfig?: Record<string, any>
12
- vlConfig?: Record<string, any>
13
- parent?: { vlConfig?: Record<string, any> }
14
- }) => {
15
- testId++
16
- const root = path.join(BASE_TMP, `t${testId}`)
17
- const projectDir = opts.parent ? path.join(root, 'packages', 'child') : root
18
-
19
- mkdirSync(projectDir, { recursive: true })
20
-
21
- writeFileSync(
22
- path.join(projectDir, 'package.json'),
23
- JSON.stringify(opts.packageJson ?? { name: 'test-pkg' }),
24
- )
25
-
26
- if (opts.tsConfig) {
27
- writeFileSync(
28
- path.join(projectDir, 'tsconfig.json'),
29
- JSON.stringify(opts.tsConfig),
30
- )
31
- }
32
-
33
- if (opts.vlConfig) {
34
- writeFileSync(
35
- path.join(projectDir, 'vl-tools.config.mjs'),
36
- `export default ${JSON.stringify(opts.vlConfig)}`,
37
- )
38
- }
39
-
40
- if (opts.parent?.vlConfig) {
41
- writeFileSync(
42
- path.join(root, 'vl-tools.config.mjs'),
43
- `export default ${JSON.stringify(opts.parent.vlConfig)}`,
44
- )
45
- }
46
-
47
- return projectDir
48
- }
49
-
50
- afterAll(() => {
51
- rmSync(BASE_TMP, { recursive: true, force: true })
52
- })
53
-
54
- describe('tools-core', () => {
55
- beforeEach(() => {
56
- vi.restoreAllMocks()
57
- })
58
-
59
- describe('swapGlobals', () => {
60
- it('should invert key/value pairs', async () => {
61
- vi.resetModules()
62
- const dir = createTestDir({})
63
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
64
-
65
- const mod = await import('./index.js')
66
- const input = { react: 'React', 'react-dom': 'ReactDOM' }
67
- expect(mod.swapGlobals(input)).toEqual({
68
- React: 'react',
69
- ReactDOM: 'react-dom',
70
- })
71
- })
72
-
73
- it('should return empty object for empty input', async () => {
74
- vi.resetModules()
75
- const dir = createTestDir({})
76
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
77
-
78
- const mod = await import('./index.js')
79
- expect(mod.swapGlobals({})).toEqual({})
80
- })
81
- })
82
-
83
- describe('defineConfig', () => {
84
- it('should return the same config object', async () => {
85
- vi.resetModules()
86
- const dir = createTestDir({})
87
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
88
-
89
- const mod = await import('./index.js')
90
- const config = { stories: { framework: 'next' } }
91
- expect(mod.defineConfig(config)).toBe(config)
92
- })
93
- })
94
-
95
- describe('findFile', () => {
96
- it('should return the path when file is found in cwd', async () => {
97
- vi.resetModules()
98
- const dir = createTestDir({ tsConfig: { strict: true } })
99
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
100
-
101
- const mod = await import('./index.js')
102
- expect(mod.findFile('tsconfig.json')).toBe(
103
- path.join(dir, 'tsconfig.json'),
104
- )
105
- })
106
-
107
- it('should walk up directories to find the file', async () => {
108
- vi.resetModules()
109
- testId++
110
- const root = path.join(BASE_TMP, `t${testId}`)
111
- const child = path.join(root, 'sub', 'deep')
112
- mkdirSync(child, { recursive: true })
113
- writeFileSync(
114
- path.join(child, 'package.json'),
115
- JSON.stringify({ name: 'deep' }),
116
- )
117
- writeFileSync(path.join(root, 'target.json'), '{}')
118
- vi.spyOn(process, 'cwd').mockReturnValue(child)
119
-
120
- const mod = await import('./index.js')
121
- expect(mod.findFile('target.json')).toBe(path.join(root, 'target.json'))
122
- })
123
-
124
- it('should return undefined when file is not found', async () => {
125
- vi.resetModules()
126
- const dir = createTestDir({})
127
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
128
-
129
- const mod = await import('./index.js')
130
- expect(mod.findFile('nonexistent.xyz')).toBeUndefined()
131
- })
132
- })
133
-
134
- describe('loadFileToJSON', () => {
135
- it('should return empty object when file is not found', async () => {
136
- vi.resetModules()
137
- const dir = createTestDir({})
138
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
139
-
140
- const mod = await import('./index.js')
141
- expect(mod.loadFileToJSON('missing.json')).toEqual({})
142
- })
143
-
144
- it('should parse JSON files', async () => {
145
- vi.resetModules()
146
- const dir = createTestDir({
147
- tsConfig: { compilerOptions: { strict: true } },
148
- })
149
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
150
-
151
- const mod = await import('./index.js')
152
- expect(mod.loadFileToJSON('tsconfig.json')).toEqual({
153
- compilerOptions: { strict: true },
154
- })
155
- })
156
-
157
- it('should return empty object for invalid JSON', async () => {
158
- vi.resetModules()
159
- const dir = createTestDir({})
160
- writeFileSync(path.join(dir, 'bad.json'), 'not json{{{')
161
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
162
-
163
- const mod = await import('./index.js')
164
- expect(mod.loadFileToJSON('bad.json')).toEqual({})
165
- })
166
- })
167
-
168
- describe('loadConfigParam', () => {
169
- it('should return a function that gets a nested config value', async () => {
170
- vi.resetModules()
171
- const dir = createTestDir({})
172
- writeFileSync(
173
- path.join(dir, 'config.json'),
174
- JSON.stringify({ build: { sourceDir: 'src' } }),
175
- )
176
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
177
-
178
- const mod = await import('./index.js')
179
- const getParam = mod.loadConfigParam('config.json')
180
- expect(getParam('build.sourceDir')).toBe('src')
181
- })
182
-
183
- it('should return defaultValue when key is not found', async () => {
184
- vi.resetModules()
185
- const dir = createTestDir({})
186
- writeFileSync(path.join(dir, 'config.json'), JSON.stringify({}))
187
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
188
-
189
- const mod = await import('./index.js')
190
- const getParam = mod.loadConfigParam('config.json')
191
- expect(getParam('missing.key', 'default')).toBe('default')
192
- })
193
- })
194
-
195
- describe('loadVLToolsConfig', () => {
196
- it('should load .mjs config and provide .config, .get(), .merge()', async () => {
197
- vi.resetModules()
198
- const dir = createTestDir({
199
- vlConfig: { build: { sourceDir: 'src' } },
200
- })
201
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
202
-
203
- const mod = await import('./index.js')
204
- const vlConfig = await mod.loadVLToolsConfig()
205
- const buildConfig = vlConfig('build')
206
- expect(buildConfig.config).toEqual({ sourceDir: 'src' })
207
- expect(buildConfig.get('sourceDir')).toBe('src')
208
- })
209
-
210
- it('should support chained merge calls', async () => {
211
- vi.resetModules()
212
- const dir = createTestDir({
213
- vlConfig: { build: { sourceDir: 'src' } },
214
- })
215
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
216
-
217
- const mod = await import('./index.js')
218
- const vlConfig = await mod.loadVLToolsConfig()
219
- const merged = vlConfig('build').merge({ outputDir: 'lib' })
220
- expect(merged.config).toEqual({ sourceDir: 'src', outputDir: 'lib' })
221
- })
222
-
223
- it('should return empty config when no config file exists', async () => {
224
- vi.resetModules()
225
- const dir = createTestDir({})
226
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
227
-
228
- const mod = await import('./index.js')
229
- const vlConfig = await mod.loadVLToolsConfig()
230
- expect(vlConfig('build').config).toEqual({})
231
- })
232
-
233
- it('should return default value with get when key is missing', async () => {
234
- vi.resetModules()
235
- const dir = createTestDir({})
236
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
237
-
238
- const mod = await import('./index.js')
239
- const vlConfig = await mod.loadVLToolsConfig()
240
- expect(vlConfig('build').get('missing')).toEqual({})
241
- })
242
-
243
- it('should cascade configs from root to package (deep merge)', async () => {
244
- vi.resetModules()
245
- const dir = createTestDir({
246
- vlConfig: { stories: { framework: 'next' } },
247
- parent: {
248
- vlConfig: {
249
- stories: { framework: 'vite', port: 6006 },
250
- build: { sourceDir: 'src' },
251
- },
252
- },
253
- })
254
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
255
-
256
- const mod = await import('./index.js')
257
- const vlConfig = await mod.loadVLToolsConfig()
258
- const stories = vlConfig('stories')
259
-
260
- // framework overridden by package config
261
- expect(stories.get('framework')).toBe('next')
262
- // port inherited from root config
263
- expect(stories.get('port')).toBe(6006)
264
- // build inherited from root config
265
- expect(vlConfig('build').config).toEqual({ sourceDir: 'src' })
266
- })
267
- })
268
-
269
- describe('module-level constants', () => {
270
- it('should export PKG with bundleName from scoped package name', async () => {
271
- vi.resetModules()
272
- const dir = createTestDir({
273
- packageJson: {
274
- name: '@test/pkg',
275
- version: '1.0.0',
276
- dependencies: { react: '^19' },
277
- },
278
- })
279
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
280
-
281
- const mod = await import('./index.js')
282
- expect(mod.PKG.name).toBe('@test/pkg')
283
- expect(mod.PKG.bundleName).toBe('testPkg')
284
- expect(mod.PKG.externalDependencies).toContain('react')
285
- })
286
-
287
- it('should handle simple hyphenated package names in bundleName', async () => {
288
- vi.resetModules()
289
- const dir = createTestDir({
290
- packageJson: { name: 'my-cool-library' },
291
- })
292
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
293
-
294
- const mod = await import('./index.js')
295
- expect(mod.PKG.bundleName).toBe('myCoolLibrary')
296
- })
297
-
298
- it('should include peerDependencies in externalDependencies', async () => {
299
- vi.resetModules()
300
- const dir = createTestDir({
301
- packageJson: {
302
- name: 'my-lib',
303
- peerDependencies: { 'styled-components': '^6' },
304
- },
305
- })
306
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
307
-
308
- const mod = await import('./index.js')
309
- expect(mod.PKG.externalDependencies).toContain('styled-components')
310
- })
311
-
312
- it('should export VL_CONFIG as a function', async () => {
313
- vi.resetModules()
314
- const dir = createTestDir({})
315
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
316
-
317
- const mod = await import('./index.js')
318
- expect(typeof mod.VL_CONFIG).toBe('function')
319
- })
320
-
321
- it('should export TS_CONFIG from tsconfig.json', async () => {
322
- vi.resetModules()
323
- const dir = createTestDir({
324
- tsConfig: { compilerOptions: { strict: true } },
325
- })
326
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
327
-
328
- const mod = await import('./index.js')
329
- expect(mod.TS_CONFIG).toEqual({ compilerOptions: { strict: true } })
330
- })
331
-
332
- it('should resolve VL_CONFIG from .mjs config at module level', async () => {
333
- vi.resetModules()
334
- const dir = createTestDir({
335
- vlConfig: { stories: { framework: 'next', port: 3000 } },
336
- })
337
- vi.spyOn(process, 'cwd').mockReturnValue(dir)
338
-
339
- const mod = await import('./index.js')
340
- const stories = mod.VL_CONFIG('stories')
341
- expect(stories.get('framework')).toBe('next')
342
- expect(stories.get('port')).toBe(3000)
343
- })
344
- })
345
- })
package/src/index.ts DELETED
@@ -1,249 +0,0 @@
1
- import fs from 'node:fs'
2
- import path from 'node:path'
3
- import { pathToFileURL } from 'node:url'
4
-
5
- const VL_CONFIG_FILES = ['vl-tools.config.mjs']
6
- const PACKAGE_FILE_NAME = 'package.json'
7
- const TYPESCRIPT_FILE_NAME = 'tsconfig.json'
8
-
9
- // --------------------------------------------------------
10
- // Utility helpers (replaces lodash-es and find-up)
11
- // --------------------------------------------------------
12
- const get = (obj: any, dotPath: string, defaultValue: any = {}): any => {
13
- const keys = dotPath.split('.')
14
- let result = obj
15
-
16
- for (const key of keys) {
17
- if (result == null) return defaultValue
18
- result = result[key]
19
- }
20
-
21
- return result === undefined ? defaultValue : result
22
- }
23
-
24
- const deepMerge = (
25
- target: Record<string, any>,
26
- source: Record<string, any>,
27
- ): Record<string, any> => {
28
- const result = { ...target }
29
-
30
- for (const key of Object.keys(source)) {
31
- const srcVal = source[key]
32
- const tgtVal = result[key]
33
-
34
- if (
35
- typeof srcVal === 'object' &&
36
- srcVal !== null &&
37
- !Array.isArray(srcVal) &&
38
- typeof tgtVal === 'object' &&
39
- tgtVal !== null &&
40
- !Array.isArray(tgtVal)
41
- ) {
42
- result[key] = deepMerge(tgtVal, srcVal)
43
- } else {
44
- result[key] = srcVal
45
- }
46
- }
47
-
48
- return result
49
- }
50
-
51
- const findFileUp = (
52
- names: string | string[],
53
- cwd = process.cwd(),
54
- ): string | undefined => {
55
- const fileNames = Array.isArray(names) ? names : [names]
56
- let dir = path.resolve(cwd)
57
-
58
- while (true) {
59
- for (const name of fileNames) {
60
- const filePath = path.join(dir, name)
61
- try {
62
- if (fs.statSync(filePath).isFile()) return filePath
63
- } catch (_e) {
64
- // file doesn't exist, continue
65
- }
66
- }
67
-
68
- const parent = path.dirname(dir)
69
- if (parent === dir) return undefined
70
- dir = parent
71
- }
72
- }
73
-
74
- // --------------------------------------------------------
75
- // FIND & READ file helpers
76
- // --------------------------------------------------------
77
- const findFile = (filename: string) => findFileUp(filename)
78
-
79
- const loadFileToJSON = (filename: string): Record<string, any> => {
80
- const file = findFile(filename)
81
- if (!file) return {}
82
-
83
- try {
84
- return JSON.parse(fs.readFileSync(file, 'utf-8'))
85
- } catch (_e) {
86
- return {}
87
- }
88
- }
89
-
90
- const loadModuleAsync = async (
91
- filePath: string,
92
- ): Promise<Record<string, any>> => {
93
- try {
94
- const mod = await import(pathToFileURL(filePath).href)
95
- return mod?.default ?? mod ?? {}
96
- } catch (e: any) {
97
- console.warn(
98
- `[tools-core] Failed to load config: ${filePath}\n ${e.message}`,
99
- )
100
- return {}
101
- }
102
- }
103
-
104
- // --------------------------------------------------------
105
- // GET PACKAGE.JSON info
106
- // --------------------------------------------------------
107
- const getPackageJSON = () => loadFileToJSON(PACKAGE_FILE_NAME)
108
-
109
- // --------------------------------------------------------
110
- // PACKAGE.json parsing functions
111
- // --------------------------------------------------------
112
-
113
- // GET LIST OF DEPENDENCIES from package.json
114
- const getDependenciesList = (types: any) => {
115
- const pkg = getPackageJSON()
116
- let result: any = []
117
-
118
- types.forEach((item: any) => {
119
- const data = pkg[item]
120
- result = [...result, ...Object.keys(data || {})]
121
- })
122
-
123
- return result
124
- }
125
-
126
- // converts package name to umd or iife valid format
127
- // example: napespace-package-name => namespacePackageName
128
- const camelspaceBundleName = (name: string) => {
129
- const parsedName = name.replace('@', '').replace('/', '-')
130
- const toCamelCase = (items: any) =>
131
- items.map((item: any, i: any) =>
132
- i === 0
133
- ? item
134
- : item.charAt(0).toUpperCase() + item.slice(1).toLowerCase(),
135
- )
136
- const parts = parsedName.split('-')
137
- const result = toCamelCase(parts).join('')
138
-
139
- return result
140
- }
141
-
142
- // --------------------------------------------------------
143
- // PACKAGE JSON DATA
144
- // --------------------------------------------------------
145
- const getPkgData = (): Record<string, any> => {
146
- const pkg = getPackageJSON()
147
- const { name } = pkg
148
-
149
- return {
150
- ...pkg,
151
- bundleName: camelspaceBundleName(name),
152
- externalDependencies: getDependenciesList([
153
- 'dependencies',
154
- 'peerDependencies',
155
- ]),
156
- }
157
- }
158
-
159
- // --------------------------------------------------------
160
- // LOAD EXTERNAL CONFIGURATION
161
- // Cascading: finds all vl-tools.config.mjs files from
162
- // cwd upward, then deep-merges them (root first, closest
163
- // package config wins).
164
- // --------------------------------------------------------
165
- const findAllConfigFiles = (): string[] => {
166
- const files: string[] = []
167
- let cwd = process.cwd()
168
-
169
- while (true) {
170
- const file = findFileUp(VL_CONFIG_FILES, cwd)
171
- if (!file) break
172
- files.push(file)
173
- const parentDir = path.dirname(path.dirname(file))
174
- if (parentDir === path.dirname(file)) break
175
- cwd = parentDir
176
- }
177
-
178
- // Root config first, closest config last (overrides)
179
- return files.reverse()
180
- }
181
-
182
- const getExternalConfig = async (): Promise<Record<string, any>> => {
183
- const files = findAllConfigFiles()
184
- let config: Record<string, any> = {}
185
-
186
- for (const file of files) {
187
- const loaded = await loadModuleAsync(file)
188
- config = deepMerge(config, loaded)
189
- }
190
-
191
- return config
192
- }
193
-
194
- const loadConfigParam =
195
- (filename: string) =>
196
- (key: string, defaultValue = {}) => {
197
- const externalConfig = loadFileToJSON(filename)
198
-
199
- return get(externalConfig, key, defaultValue)
200
- }
201
-
202
- const loadVLToolsConfig = async () => {
203
- const externalConfig = await getExternalConfig()
204
-
205
- const cloneAndEnhance = (object: Record<string, any>) => ({
206
- get config() {
207
- return object
208
- },
209
- get: (param: string, defaultValue?: any) =>
210
- get(object, param, defaultValue || {}),
211
- merge: (param: Record<string, any>) =>
212
- cloneAndEnhance(deepMerge(param, object)),
213
- })
214
-
215
- const getOutput = (key: string) => {
216
- const result = get(externalConfig, key, {})
217
-
218
- return cloneAndEnhance(result)
219
- }
220
-
221
- return getOutput
222
- }
223
-
224
- const defineConfig = <T extends Record<string, any>>(config: T): T => config
225
-
226
- const swapGlobals = (globals: Record<string, string>) =>
227
- Object.entries(globals).reduce<Record<string, string>>(
228
- (acc, [key, value]) => {
229
- acc[value] = key
230
- return acc
231
- },
232
- {},
233
- )
234
-
235
- const PKG = getPkgData()
236
- const VL_CONFIG = await loadVLToolsConfig()
237
- const TS_CONFIG = loadFileToJSON(TYPESCRIPT_FILE_NAME)
238
-
239
- export {
240
- defineConfig,
241
- findFile,
242
- loadConfigParam,
243
- loadFileToJSON,
244
- loadVLToolsConfig,
245
- swapGlobals,
246
- PKG,
247
- VL_CONFIG,
248
- TS_CONFIG,
249
- }
package/tsconfig.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "extends": "@vitus-labs/tools-typescript/lib",
3
- "compilerOptions": {
4
- "noEmit": false,
5
- "outDir": "lib",
6
- "rootDir": "src",
7
- "baseUrl": ".",
8
- "declarationDir": "./lib/types",
9
- "paths": {
10
- "~/*": ["src/*"]
11
- }
12
- },
13
- "include": ["typings", "src"],
14
- "exclude": ["node_modules", "__stories__", "lib", "**/*.test.ts"]
15
- }
package/vitest.config.ts DELETED
@@ -1,3 +0,0 @@
1
- import { createVitestConfig } from '../../vitest.shared.js'
2
-
3
- export default createVitestConfig()